/ src / bitbucket_api.adb
bitbucket_api.adb
  1  -- SPDX-License-Identifier: AGPL-3.0-or-later
  2  
  3  with GNAT.OS_Lib;
  4  with GNAT.Expect;
  5  with Ada.Text_IO;
  6  
  7  package body Bitbucket_API is
  8  
  9     Base_URL : constant String := "https://api.bitbucket.org/2.0";
 10  
 11     function Run_Curl
 12       (Args : String) return API_Result
 13     is
 14        use GNAT.Expect;
 15        Pd : Process_Descriptor;
 16        Result : Expect_Match;
 17        Output : Unbounded_String := Null_Unbounded_String;
 18        Ret : API_Result;
 19     begin
 20        Non_Blocking_Spawn
 21          (Pd,
 22           "/usr/bin/curl",
 23           GNAT.OS_Lib.Argument_String_To_List (Args).all,
 24           Err_To_Out => True);
 25  
 26        loop
 27           begin
 28              Expect (Pd, Result, ".+", Timeout => 30_000);
 29              Append (Output, Expect_Out (Pd));
 30           exception
 31              when Process_Died =>
 32                 exit;
 33           end;
 34        end loop;
 35  
 36        Close (Pd);
 37  
 38        Ret.Data := Output;
 39  
 40        if Index (Output, """error""") > 0 or else
 41           Index (Output, "\"error\"") > 0
 42        then
 43           Ret.Success := False;
 44           Ret.Message := To_Unbounded_String ("API error");
 45        else
 46           Ret.Success := True;
 47           Ret.Message := To_Unbounded_String ("OK");
 48        end if;
 49  
 50        return Ret;
 51  
 52     exception
 53        when others =>
 54           Ret.Success := False;
 55           Ret.Message := To_Unbounded_String ("Failed to execute curl");
 56           return Ret;
 57     end Run_Curl;
 58  
 59     function Create_Repo
 60       (Creds : Config.Credentials;
 61        Name : String;
 62        Is_Private : Boolean := False;
 63        Description : String := "") return API_Result
 64     is
 65        URL : constant String :=
 66           Base_URL & "/repositories/" &
 67           To_String (Creds.Workspace) & "/" & Name;
 68        Private_Str : constant String :=
 69           (if Is_Private then "true" else "false");
 70        Data : constant String :=
 71           "{""scm"":""git"",""is_private"":" & Private_Str &
 72           ",""description"":""" & Description & """}";
 73        Args : constant String :=
 74           "-s -X POST " &
 75           "-u " & To_String (Creds.Username) & ":" &
 76           To_String (Creds.App_Password) & " " &
 77           "-H ""Content-Type: application/json"" " &
 78           "-d '" & Data & "' " &
 79           URL;
 80     begin
 81        return Run_Curl (Args);
 82     end Create_Repo;
 83  
 84     function Delete_Repo
 85       (Creds : Config.Credentials;
 86        Name : String) return API_Result
 87     is
 88        URL : constant String :=
 89           Base_URL & "/repositories/" &
 90           To_String (Creds.Workspace) & "/" & Name;
 91        Args : constant String :=
 92           "-s -X DELETE " &
 93           "-u " & To_String (Creds.Username) & ":" &
 94           To_String (Creds.App_Password) & " " &
 95           URL;
 96     begin
 97        return Run_Curl (Args);
 98     end Delete_Repo;
 99  
100     function List_Repos
101       (Creds : Config.Credentials) return API_Result
102     is
103        URL : constant String :=
104           Base_URL & "/repositories/" &
105           To_String (Creds.Workspace) & "?pagelen=100";
106        Args : constant String :=
107           "-s -X GET " &
108           "-u " & To_String (Creds.Username) & ":" &
109           To_String (Creds.App_Password) & " " &
110           URL;
111     begin
112        return Run_Curl (Args);
113     end List_Repos;
114  
115     function Get_Repo
116       (Creds : Config.Credentials;
117        Name : String) return API_Result
118     is
119        URL : constant String :=
120           Base_URL & "/repositories/" &
121           To_String (Creds.Workspace) & "/" & Name;
122        Args : constant String :=
123           "-s -X GET " &
124           "-u " & To_String (Creds.Username) & ":" &
125           To_String (Creds.App_Password) & " " &
126           URL;
127     begin
128        return Run_Curl (Args);
129     end Get_Repo;
130  
131     function Repo_Exists
132       (Creds : Config.Credentials;
133        Name : String) return Boolean
134     is
135        Result : constant API_Result := Get_Repo (Creds, Name);
136     begin
137        return Result.Success and then
138           Index (Result.Data, """slug"":""" & Name & """") > 0;
139     end Repo_Exists;
140  
141  end Bitbucket_API;