From 91abf257884b46079ab768ac773255f79ba07716 Mon Sep 17 00:00:00 2001 From: "Rigoberto L. Perez" Date: Fri, 24 Oct 2025 00:00:12 -0400 Subject: [PATCH 1/5] feature: Add git get repos command --- src/bb_utils/core.bb | 7 ++++++- src/bb_utils/git.bb | 34 ++++++++++++++++++++++++++++++++++ src/bb_utils/string.bb | 1 + 3 files changed, 41 insertions(+), 1 deletion(-) create mode 100644 src/bb_utils/git.bb diff --git a/src/bb_utils/core.bb b/src/bb_utils/core.bb index 803a8e2..8a493f1 100755 --- a/src/bb_utils/core.bb +++ b/src/bb_utils/core.bb @@ -1,18 +1,22 @@ #!/usr/bin/env bb + (ns bb-utils.core (:require [babashka.cli :as cli] - [bb-utils.string :refer [from-base64 from-hex]])) + [bb-utils.string :refer [from-base64 from-hex]] + [bb-utils.git :refer [get-repos]])) (defn help [_] (println "Usage: bbut [...args]") (println "\nAvailable commands:") (println " string from-base64 Convert Base64 to string") (println " string from-hex Convert hex to string") + (println " git get-repos [path] Lists all git repos at path. Default path '.'") (println "\nUse 'bbut --help' for help.")) (def table [{:cmds ["string" "from-hex"] :fn (fn [{:keys [args]}] (println (from-hex (first args))))} {:cmds ["string" "from-base64"] :fn (fn [{:keys [args]}] (println (from-base64 (first args))))} + {:cmds ["git" "get-repos"] :fn (fn [{:keys [args]}] (run! println (get-repos (first args))))} {:cmds ["--help"] :fn help} {:cmds [] :fn help}]) @@ -26,3 +30,4 @@ (when (= *file* (System/getProperty "babashka.file")) (apply -main *command-line-args*)) + diff --git a/src/bb_utils/git.bb b/src/bb_utils/git.bb new file mode 100644 index 0000000..116241e --- /dev/null +++ b/src/bb_utils/git.bb @@ -0,0 +1,34 @@ +#!/usr/bin/env bb + +(ns bb-utils.git + (:require [babashka.process :refer [shell]] + [babashka.fs :as fs] + [clojure.string :as str])) + +(defn- filter-current-branch + [output] + (let [branches (str/split-lines output)] + (first (filter #(str/starts-with? % "*") branches)))) + +(defn- get-current-branch + [path] + (let [branch (-> (shell {:out :string :dir path} "git" "branch") :out filter-current-branch)] + (if branch + (subs branch 2) + nil))) + +(defn- any-changes? + [path] + (not (str/blank? (-> (shell {:out :string :dir path} "git" "status" "--short") :out str)))) + +(defn- git-repo? + [path] + (and (fs/directory? path) + (fs/exists? (str path "/.git")))) + +(defn get-repos + [path] + (let [base-path (or path ".")] + (println base-path) + (map #(.toString %) (filter git-repo? (fs/list-dir base-path))))) + diff --git a/src/bb_utils/string.bb b/src/bb_utils/string.bb index c48f4c6..632b320 100644 --- a/src/bb_utils/string.bb +++ b/src/bb_utils/string.bb @@ -1,4 +1,5 @@ #!/usr/bin/env bb + (ns bb-utils.string (:import [java.util Base64])) From 80d082c66d239caeace3e630c36ed24c7250d55b Mon Sep 17 00:00:00 2001 From: "Rigoberto L. Perez" Date: Sat, 25 Oct 2025 21:06:13 -0400 Subject: [PATCH 2/5] feature: Add git pull-all command without any flags --- src/bb_utils/core.bb | 15 +++++++++++---- src/bb_utils/git.bb | 18 +++++++++++++++--- 2 files changed, 26 insertions(+), 7 deletions(-) diff --git a/src/bb_utils/core.bb b/src/bb_utils/core.bb index 8a493f1..27b015d 100755 --- a/src/bb_utils/core.bb +++ b/src/bb_utils/core.bb @@ -3,20 +3,27 @@ (ns bb-utils.core (:require [babashka.cli :as cli] [bb-utils.string :refer [from-base64 from-hex]] - [bb-utils.git :refer [get-repos]])) + [bb-utils.git :refer [get-repos pull-all]])) (defn help [_] (println "Usage: bbut [...args]") (println "\nAvailable commands:") - (println " string from-base64 Convert Base64 to string") - (println " string from-hex Convert hex to string") - (println " git get-repos [path] Lists all git repos at path. Default path '.'") + (println " string from-base64 Convert Base64 to string") + (println " string from-hex Convert hex to string") + (println " git get-repos [path] Lists all git repos at path. Default path '.'") + (println " git pull-all [path] [branch] Pull all repos at path. Default path '.'. Default branch is current branch") + (println " Options:") + (println "TODO [branch] Checkout the branch and pull") + (println "TODO --include-changed Stashes changes, pull, then apply the changes") + (println "TODO --reset-branch Returns repo to original branch, if combined with --include-changed will apply changes on original branch") + (println "TODO --merge Use with [branch] and if current branch is not original branch it will merge original branch into given branch") (println "\nUse 'bbut --help' for help.")) (def table [{:cmds ["string" "from-hex"] :fn (fn [{:keys [args]}] (println (from-hex (first args))))} {:cmds ["string" "from-base64"] :fn (fn [{:keys [args]}] (println (from-base64 (first args))))} {:cmds ["git" "get-repos"] :fn (fn [{:keys [args]}] (run! println (get-repos (first args))))} + {:cmds ["git" "pull-all"] :fn (fn [{:keys [args]}] (pull-all (first args)))} {:cmds ["--help"] :fn help} {:cmds [] :fn help}]) diff --git a/src/bb_utils/git.bb b/src/bb_utils/git.bb index 116241e..5e98226 100644 --- a/src/bb_utils/git.bb +++ b/src/bb_utils/git.bb @@ -17,9 +17,14 @@ (subs branch 2) nil))) +(defn- change? [line] + (and (not-empty line) + (and (>= (count line) 2) + (not (= (subs line 0 2) "??"))))) + (defn- any-changes? [path] - (not (str/blank? (-> (shell {:out :string :dir path} "git" "status" "--short") :out str)))) + (some change? (str/split-lines (-> (shell {:out :string :dir path} "git" "status" "--short") :out str)))) (defn- git-repo? [path] @@ -28,7 +33,14 @@ (defn get-repos [path] - (let [base-path (or path ".")] - (println base-path) + (let [base-path (or path "./")] (map #(.toString %) (filter git-repo? (fs/list-dir base-path))))) +(defn pull-all + [path] + (let [base-path (or path "./") + repos (get-repos base-path)] + (map #((if (any-changes? (str base-path %)) + (println (str "Skipping " % ". Uncommitted changes found.")) + (shell {:out :string :dir (str base-path %)} "git" "pull"))) + repos))) From a2cf19cc3f86bd8c81f96f8d46253118da7796a6 Mon Sep 17 00:00:00 2001 From: "Rigoberto L. Perez" Date: Sat, 25 Oct 2025 21:10:21 -0400 Subject: [PATCH 3/5] refactor: use doseq instead of map since map is lazy and this is side effect driven --- src/bb_utils/git.bb | 27 ++++++++++++++++++++------- 1 file changed, 20 insertions(+), 7 deletions(-) diff --git a/src/bb_utils/git.bb b/src/bb_utils/git.bb index 5e98226..6a60a28 100644 --- a/src/bb_utils/git.bb +++ b/src/bb_utils/git.bb @@ -5,6 +5,14 @@ [babashka.fs :as fs] [clojure.string :as str])) +(defn get-path-or-default + ([path] + (get-path-or-default path nil)) + ([path rest] + (let [path (or path "./") + rest (or rest nil)] + (str/replace (str path rest) "/./" "/")))) + (defn- filter-current-branch [output] (let [branches (str/split-lines output)] @@ -33,14 +41,19 @@ (defn get-repos [path] - (let [base-path (or path "./")] + (let [base-path (get-path-or-default path)] (map #(.toString %) (filter git-repo? (fs/list-dir base-path))))) +(defn pull + [path] + (if (any-changes? path) + (println (str "Skipping " path ". Uncommitted changes found.")) + (shell {:out :string :dir path} "git" "pull"))) + (defn pull-all [path] - (let [base-path (or path "./") - repos (get-repos base-path)] - (map #((if (any-changes? (str base-path %)) - (println (str "Skipping " % ". Uncommitted changes found.")) - (shell {:out :string :dir (str base-path %)} "git" "pull"))) - repos))) + (let [path (get-path-or-default path) + repos (get-repos path)] + (doseq [repo-path repos] + (let [full-repo-path (get-path-or-default path repo-path)] + (pull full-repo-path))))) From 87fdcd803bfb6808ca05911ed2ce7e1de3ae5733 Mon Sep 17 00:00:00 2001 From: "Rigoberto L. Perez" Date: Mon, 8 Dec 2025 09:51:37 -0500 Subject: [PATCH 4/5] =?UTF-8?q?test=20=F0=9F=A7=AA:=20add=20tests=20for=20?= =?UTF-8?q?git=20command?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Rigoberto L. Perez --- test/bb_utils/git_test.bb | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 test/bb_utils/git_test.bb diff --git a/test/bb_utils/git_test.bb b/test/bb_utils/git_test.bb new file mode 100644 index 0000000..c26d011 --- /dev/null +++ b/test/bb_utils/git_test.bb @@ -0,0 +1,8 @@ +#!/usr/bin/env bb + +(ns bb-utils.git-test + (:require [clojure.test :refer [deftest is]] + [bb-utils.git :as git])) + +(deftest test-get-current-branch + (let [])) From 96f6c1d6e8319f3bb2ab1817a809ce46275e0b4d Mon Sep 17 00:00:00 2001 From: "Rigoberto L. Perez" Date: Mon, 8 Dec 2025 09:52:16 -0500 Subject: [PATCH 5/5] feature: add some branching commands to git --- src/bb_utils/git.bb | 46 +++++++++++++++++++++++++++++---------------- 1 file changed, 30 insertions(+), 16 deletions(-) diff --git a/src/bb_utils/git.bb b/src/bb_utils/git.bb index 6a60a28..36efa1a 100644 --- a/src/bb_utils/git.bb +++ b/src/bb_utils/git.bb @@ -5,6 +5,18 @@ [babashka.fs :as fs] [clojure.string :as str])) +(defn git-branch + [repo-path] + (shell {:out :string :dir repo-path} "git" "branch")) + +(defn git-status-short + [repo-path] + (shell {:out :string :dir repo-path} "git" "status" "--short")) + +(defn git-pull + [repo-path] + (shell {:out :string :dir repo-path} "git" "pull")) + (defn get-path-or-default ([path] (get-path-or-default path nil)) @@ -13,31 +25,33 @@ rest (or rest nil)] (str/replace (str path rest) "/./" "/")))) -(defn- filter-current-branch +(defn filter-current-branch [output] (let [branches (str/split-lines output)] (first (filter #(str/starts-with? % "*") branches)))) -(defn- get-current-branch - [path] - (let [branch (-> (shell {:out :string :dir path} "git" "branch") :out filter-current-branch)] +(defn get-current-branch + ;; TODO: Detached head doesn't seem right. + ;; Probably should skip this if it happens + [repo-path] + (let [branch (filter-current-branch (git-branch repo-path))] (if branch (subs branch 2) nil))) -(defn- change? [line] +(defn changes? [line] (and (not-empty line) (and (>= (count line) 2) (not (= (subs line 0 2) "??"))))) -(defn- any-changes? - [path] - (some change? (str/split-lines (-> (shell {:out :string :dir path} "git" "status" "--short") :out str)))) +(defn any-changes? + [repo-path] + (some changes? (str/split-lines (str (git-status-short repo-path))))) -(defn- git-repo? - [path] - (and (fs/directory? path) - (fs/exists? (str path "/.git")))) +(defn git-repo? + [repo-path] + (and (fs/directory? repo-path) + (fs/exists? (str repo-path "/.git")))) (defn get-repos [path] @@ -45,10 +59,10 @@ (map #(.toString %) (filter git-repo? (fs/list-dir base-path))))) (defn pull - [path] - (if (any-changes? path) - (println (str "Skipping " path ". Uncommitted changes found.")) - (shell {:out :string :dir path} "git" "pull"))) + [repo-path] + (if (any-changes? repo-path) + (println (str "Skipping " repo-path ". Uncommitted changes found.")) + (git-pull repo-path))) (defn pull-all [path]