Created
January 16, 2025 01:56
-
-
Save chase-lambert/f97bd336ddeedbabb979a42ba4463847 to your computer and use it in GitHub Desktop.
Concatenates all your git repo's clojure files into one file
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env bb | |
;; A Babashka script to concatenate all Clojure files in a repository into a single file. | |
;; Respects .gitignore patterns and includes clear file separation markers. | |
;; | |
;; Usage: | |
;; ./onefile.clj ; uses current git repo and default output | |
;; ./onefile.clj /path/to/repo ; uses custom repo path | |
;; ./onefile.clj /path/to/repo out.clj ; specifies output filename | |
;; | |
;; The output file will be created in the current directory. | |
(ns onefile | |
(:require [babashka.fs :as fs] | |
[clojure.string :as str] | |
[babashka.process :refer [shell]])) | |
(defn gitignore-pattern->regex [pattern] | |
(-> pattern | |
(str/replace #"\." "\\.") | |
(str/replace #"\*" ".*") | |
(str/replace #"\?" ".") | |
(str/replace #"\[" "\\[") | |
(str/replace #"\]" "\\]") | |
(str/replace #"\(" "\\(") | |
(str/replace #"\)" "\\)") | |
(str/replace #"\+" "\\+") | |
(str/replace #"\{" "\\{") | |
(str/replace #"\}" "\\}") | |
(str/replace #"\^" "\\^") | |
(str/replace #"\$" "\\$"))) | |
(defn read-gitignore | |
"Read .gitignore patterns and convert them to regex patterns" | |
[path] | |
(when (fs/exists? (fs/path path ".gitignore")) | |
(->> (slurp (str path "/.gitignore")) | |
(str/split-lines) | |
(remove str/blank?) | |
(remove #(str/starts-with? % "#")) | |
(map gitignore-pattern->regex)))) | |
(defn matches-gitignore? | |
"Check if a path matches any gitignore patterns" | |
[patterns path] | |
(when (seq patterns) | |
(let [path-str (str path)] | |
(some #(re-find (re-pattern %) path-str) patterns)))) | |
(defn clojure-file? [path] | |
(let [ext (fs/extension path)] | |
(contains? #{"clj" "cljc" "cljs"} ext))) | |
(defn get-clojure-files | |
"Get all Clojure files in directory respecting .gitignore" | |
[dir] | |
(let [gitignore-patterns (read-gitignore dir)] | |
(->> (fs/glob dir "**") | |
(remove #(matches-gitignore? gitignore-patterns %)) | |
(filter fs/regular-file?) | |
(filter clojure-file?) | |
(sort)))) | |
(defn format-file-content | |
"Format file content with header comment" | |
[file content] | |
(format "\n;; =====================================\n;; File: %s\n;; =====================================\n\n%s" | |
(str file) | |
content)) | |
(defn concatenate-files [dir output-file] | |
(let [files (get-clojure-files dir) | |
content (->> files | |
(map (fn [file] | |
(format-file-content file (slurp (str file))))) | |
(str/join "\n"))] | |
(spit output-file content) | |
(println "Created" output-file "with" (count files) "files concatenated."))) | |
(defn get-git-root [] | |
(str/trim (:out (shell {:out :string} "git rev-parse --show-toplevel")))) | |
(defn -main [& args] | |
(let [dir (or (first args) (get-git-root)) | |
output-file (or (second args) "concatenated_repo.clj")] | |
(concatenate-files dir output-file))) | |
(when (= *file* (System/getProperty "babashka.file")) | |
(apply -main *command-line-args*)) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment