add automatic pull/udate of repositories

Tue, 21 Jan 2025 21:01:54 +0100

author
Mike Becker <universe@uap-core.de>
date
Tue, 21 Jan 2025 21:01:54 +0100
changeset 4
82680ce258d6
parent 3
c87bde92805f
child 5
60c2588b4455

add automatic pull/udate of repositories

src/main.cpp file | annotate | diff | comparison | revisions
src/process.cpp file | annotate | diff | comparison | revisions
src/process.h file | annotate | diff | comparison | revisions
--- a/src/main.cpp	Tue Jan 21 20:24:45 2025 +0100
+++ b/src/main.cpp	Tue Jan 21 21:01:54 2025 +0100
@@ -24,6 +24,7 @@
 
 #include "settings.h"
 #include "repositories.h"
+#include "process.h"
 
 #include <cstdlib>
 #include <cstdio>
@@ -131,18 +132,49 @@
 }
 
 int main(int argc, char *argv[]) {
+    // parse settings
     fm::settings settings;
-
     if (parse_args(settings, argc, argv)) {
         return EXIT_FAILURE;
     }
 
+    // check hg and git
+    fm::process proc;
+    proc.setbin(settings.hg);
+    if (proc.exec({"--version"})) {
+        fprintf(stderr, "Testing hg binary '%s' failed!\n", settings.hg.c_str());
+        return EXIT_FAILURE;
+    }
+    proc.setbin(settings.git);
+    if (proc.exec({"--version"})) {
+        fprintf(stderr, "Testing git binary '%s' failed!\n", settings.git.c_str());
+        return EXIT_FAILURE;
+    }
+
+    // scan for repos
     fm::repositories repos;
     for (auto &&path: settings.paths) {
         repos.scan(path, settings.depth);
     }
-    if (!settings.update_repos) {
-        // TODO: update repositories
+
+    // update repos, if not disabled
+    if (settings.update_repos) {
+        for (auto &&repo : repos.list()) {
+            proc.chdir(repo.path);
+            if (repo.type == fm::HG) {
+                proc.setbin(settings.hg);
+                if (proc.exec({"pull"})) {
+                    fprintf(stderr, "Pulling repo '%s' failed!\nMaybe there is no remote?\n", repo.path.c_str());
+                } else if (proc.exec({"update"})) {
+                    fprintf(stderr, "Updating repo '%s' failed!\nMaybe there are local changes?\n", repo.path.c_str());
+                }
+            } else {
+                proc.setbin(settings.git);
+                if (proc.exec({"pull"})) {
+                    fprintf(stderr, "Pulling repo '%s' failed!\nMaybe there is no remote or there are local changes?\n", repo.path.c_str());
+                }
+            }
+        }
     }
     // TODO: calculate the heat maps
 
--- a/src/process.cpp	Tue Jan 21 20:24:45 2025 +0100
+++ b/src/process.cpp	Tue Jan 21 21:01:54 2025 +0100
@@ -32,16 +32,23 @@
 
 using namespace fm;
 
-process::process(std::string path): m_path(std::move(path)) {
+void process::setbin(std::string path) {
+    m_path = std::move(path);
 }
 
-bool process::exec(std::vector<std::string> args) {
+void process::chdir(std::string path) {
+    m_dir = std::move(path);
+}
+
+int process::exec(std::vector<std::string> args, bool capture) {
+    m_output.clear();
+
     // fd-pair for the pipe
     int pipefd[2];
 
     if (pipe(pipefd)) {
         perror("pipe");
-        return false;
+        return -1;
     }
 
     pid_t pid = fork();
@@ -68,34 +75,40 @@
         argv[args.size() + 1] = nullptr;
 
         // execute the child program
+        if (::chdir(m_dir.c_str())) {
+            perror("chdir");
+            exit(EXIT_FAILURE);
+        }
         if (execv(m_path.c_str(), argv)) {
             perror("execl");
             exit(EXIT_FAILURE);
         }
-        return true; // unreachable, but the compiler doesn't know that
+        return 0; // unreachable, but the compiler doesn't know that
     } else if (pid > 0) {
         // close the end of the pipe we don't use
         close(pipefd[1]);
 
         // read all the output
-        char buf[64];
-        ssize_t r;
-        while ((r = read(pipefd[0], buf, sizeof(buf))) > 0) {
-            m_output.append(buf, r);
+        if (capture) {
+            char buf[64];
+            ssize_t r;
+            while ((r = read(pipefd[0], buf, sizeof(buf))) > 0) {
+                m_output.append(buf, r);
+            }
+            if (r < 0) {
+                perror("read");
+            }
+            close(pipefd[0]);
         }
-        if (r < 0) {
-            perror("read");
-        }
-        close(pipefd[0]);
 
         // wait for the process to completely finish
         int status = -1;
         waitpid(pid, &status, 0);
 
-        return status == 0;
+        return status;
     } else {
         perror("fork");
-        return false;
+        return -1;
     }
 }
 
--- a/src/process.h	Tue Jan 21 20:24:45 2025 +0100
+++ b/src/process.h	Tue Jan 21 21:01:54 2025 +0100
@@ -31,13 +31,17 @@
 namespace fm {
 
 class process final {
-    std::string m_path;
+    std::string m_path = "/bin/false";
+    std::string m_dir = ".";
     std::string m_output;
 public:
-    explicit process(std::string path);
-    ~process() = default;
+    void setbin(std::string path);
+    void chdir(std::string path);
 
-    [[nodiscard]] bool exec(std::vector<std::string> args);
+    [[nodiscard]] int exec(std::vector<std::string> args, bool capture = false);
+    [[nodiscard]] int exec_log(std::vector<std::string> args) {
+        return exec(std::move(args), true);
+    }
     [[nodiscard]] const std::string &output() const;
 };
 

mercurial