Programovací jazyk Clojure a práce s Gitem (2)

2. 7. 2015
Doba čtení: 21 minut

Sdílet

V dnešní části seriálu o jazyku Clojure i o knihovnách, které jsou pro tento jazyk dostupné, se již podruhé budeme zabývat popisem užitečné knihovny nazvané clj-jgit, která je odvozena od známé javovské knihovny JGit. Dnes si řekneme podrobnosti o práci s větvemi a taktéž o způsobu zjištění konfigurace repositáře.

Obsah

1. Programovací jazyk Clojure a práce s Gitem (2)

2. Demonstrační příklad git-test7: výpis lokálních větví repositáře

3. Demonstrační příklad git-test8: výpis vzdálených větví repositáře

4. Demonstrační příklad git-test9: přepnutí na vybranou větev (checkout)

5. Demonstrační příklad git-test10: vytvoření nové (lokální) větve

6. Demonstrační příklad git-test11: zjištění vybraných konfiguračních voleb repositáře

7. Repositář s dnešními demonstračními příklady

8. Odkazy na předchozí části seriálu

9. Odkazy na Internetu

1. Programovací jazyk Clojure a práce s Gitem (2)

Dnes se již podruhé budeme zabývat popisem knihovny clj-jgit, kterou mohou využít vývojáři používající programovací jazyk Clojure pro tvorbu svých aplikací. Již v předchozím článku jsme si řekli základní informace o této knihovně i o faktu, že se vlastně jedná o z vývojářského hlediska pěkně navržené API ke knihovně JGit, která je využívána v některých projektech naprogramovaných v Javě. Z demonstračních příkladů, které byly minule taktéž prezentovány, je zřejmé, jakým způsobem je možné naklonovat repositář, vypsat si informace o (vzdálených) větvích, přidat do repositáře nové soubory a následně provést commit. Dnes si ukážeme další možnosti, které nám knihovna clj-jgit nabízí. Především si vyzkoušíme přechod na jinou větev, tj. obdobu příkazu git checkout, dále pak zjištění informací o konfiguraci repositáře a v následující části se mj. zmíníme o jedné možnosti využití klíčů (dvojice veřejný klíč+soukromý klíč) pro přístup ke vzdálenému repositáři.

2. Demonstrační příklad git-test7: výpis lokálních větví repositáře

Dnešní první demonstrační příklad je velmi jednoduchý, protože jeho jedinou činností je výpis logovacích informací (což již známe z minula) a následně pak výpis všech lokálních větví repositáře. Pro získání sekvence všech větví, ať již lokálních či vzdálených, se používá funkce nazvaná clj-jgit.porcelain/git-branch-list, které se v nejjednodušším případě předá pouze reference na repositář získaná například s využitím již minule popsané funkce clj-jgit.porcelain/with-repo. Sekvence vrácená funkcí clj-jgit.porcelain/git-branch-list obsahuje javovské objekty typu org.eclipse.jgit.internal­.storage.file.RefDirectory. Pokud pouze potřebujeme vypsat jména větví, postačuje nad každým objektem ve vrácené sekvenci zavolat metodu .getName. Část kódu, která se postará o vypsání jmen lokálních větví, může vypadat následovně:

(defn print-local-branches
    "Vypis vsech lokalnich vetvi pro vybrany repositar."
    [repo]
    (println "\nLocal branches")
    (doseq [branch (jgit/git-branch-list repo)]
        (println (.getName branch))))

Pro vytvoření kostry demonstračního příkladu se použije příkaz, který již dokonale známe z předchozích částí tohoto seriálu:

lein new app git-7

Úprava projektového souboru project.clj spočívá v přidání dvou nových knihoven do sekce :dependencies:

(defproject git-test7 "0.1.0-SNAPSHOT"
    :description "FIXME: write description"
    :url "http://example.com/FIXME"
    :license {:name "Eclipse Public License"
              :url "http://www.eclipse.org/legal/epl-v10.html"}
    :dependencies [[org.clojure/clojure "1.6.0"]
                   [clj-jgit "0.8.0"]
                   [clj-rm-rf "1.0.0-SNAPSHOT"]]
    :main ^:skip-aot git-test7.core
    :target-path "target/%s"
    :profiles {:uberjar {:aot :all}})

Zdrojový kód souboru src/git_test7/core.clj:

(ns git-test7.core
    (:gen-class))
 
(require '[clj-jgit.porcelain :as jgit])
(require '[clj-jgit.querying  :as jgit-query])
(require '[hozumi.rm-rf :as rm-rf])
 
(def repository-url
    "Adresa GIT repositare vcetne specifikace protokolu."
    "https://github.com/tisnik/testrepo.git")
 
(def directory-name
    "Jmeno adresare, do ktereho se GIT repositar naklonuje."
    "repo")
 
(defn clone-repository
    "Naklonovani GIT repositare do specifikovaneho adresare."
    [url directory]
    (jgit/git-clone url directory))
 
(defn delete-directory
    "Smazani adresare vcetne podadresaru a souboru."
    [directory]
    (rm-rf/rm-r (java.io.File. directory)))
 
(defn print-customized-log
    "Vypis logovacich informaci ve zvolenem formatu."
    [repository]
    (println "\nLog:")
    (doseq [log-entry (jgit/git-log repository)]
        (let [info (jgit-query/commit-info repository log-entry)]
             (println (:author info) ":" (:message info)))))
 
(defn print-local-branches
    "Vypis vsech lokalnich vetvi pro vybrany repositar."
    [repo]
    (println "\nLocal branches")
    (doseq [branch (jgit/git-branch-list repo)]
        (println (.getName branch))))
 
(defn git-test-7
    "Naklonovani repositare, nacteni informaci
     z vytvoreneho adresare a vypis podrobnejsiho logu."
    [repository-url directory-name]
    ; naklonovani repositare do specifikovaneho adresare
    (clone-repository repository-url directory-name)
    ; nacteni informaci o repositari z lokalniho adresare
    ; povsimnete si pouziti "automagicky" vytvorene promenne,
    ; ktera se jmenuje 'repo'
    (try (jgit/with-repo directory-name
                         (print-customized-log repo)
                         (print-local-branches repo))
         (finally
             ; vymazani adresare s naklonovanym repositarem
             (delete-directory directory-name))))
 
(defn -main
    "Funkce zavolana po zadani prikazu 'lein run'."
    [& args]
    (git-test-7 repository-url directory-name))

Po spuštění tohoto demonstračního příkladu nad testovacím repositářem by se (pokud se tedy klonování zdařilo) měly na standardní výstup vypsat následující informace:

Log:
Pavel Tisnovsky : Added garbage
Pavel Tisnovsky : Updated README.md
Pavel Tišnovský : Initial commit
 
Local branches
refs/heads/master

Vidíme, že ihned po klonování existuje pouze jedna lokální větev, což je v pořádku.

3. Demonstrační příklad git-test8: výpis vzdálených větví repositáře

Ve druhém demonstračním příkladu se jménem git-test8 se kromě lokálních větví vypíšou i větve vzdálené (remote). Mohlo by se zdát, že pro získání vzdálených větví bude nutné použít jinou funkci než pro větve lokální, ve skutečnosti se však pro obě činnosti používá shodná funkce clj-jgit.porcelain/git-branch-list, které se však v případě potřeby předá ještě nepovinný parametr :remote (význam tohoto parametru je zřejmý), popř. je možné použít další nepovinný parametr :all (opět se zřejmým významem). Ostatně se pro zajímavost můžeme podívat na deklaraci funkce clj-jgit.porcelain/git-branch-list, která poměrně elegantním způsobem obaluje mnohem delší javovský kód (viz též http://clj-jgit.github.io/clj-jgit/:

(defn git-branch-list
  ([^Git repo]
     (git-branch-list repo :local))
  ([^Git repo opt]
     (let [opt-val {:all org.eclipse.jgit.api.ListBranchCommand$ListMode/ALL
                    :remote org.eclipse.jgit.api.ListBranchCommand$ListMode/REMOTE}
           branches (if (= opt :local)
                      (-> repo
                          (.branchList)
                          (.call))
                      (-> repo
                          (.branchList)
                          (.setListMode (opt opt-val))
                          (.call)))]
       (seq branches))))

Použití této funkce pro výpis lokálních i vzdálených větví můžeme vypadat následovně:

(defn print-local-branches
    "Vypis vsech lokalnich vetvi pro vybrany repositar."
    [repo]
    (println "\nLocal branches")
    (doseq [branch (jgit/git-branch-list repo)]
        (println (.getName branch))))
 
(defn print-remote-branches
    "Vypis vsech vzdalenych vetvi pro vybrany repositar."
    [repo]
    (println "\nRemote branches")
    (doseq [branch (jgit/git-branch-list repo :remote)]
        (println (.getName branch))))

Vytvoření kostry demonstračního příkladu:

lein new app git-8

Úprava projektového souboru project.clj je stejná, jako tomu bylo v předchozím demonstračním příkladu:

(defproject git-test8 "0.1.0-SNAPSHOT"
    :description "FIXME: write description"
    :url "http://example.com/FIXME"
    :license {:name "Eclipse Public License"
              :url "http://www.eclipse.org/legal/epl-v10.html"}
    :dependencies [[org.clojure/clojure "1.6.0"]
                   [clj-jgit "0.8.0"]
                   [clj-rm-rf "1.0.0-SNAPSHOT"]]
    :main ^:skip-aot git-test8.core
    :target-path "target/%s"
    :profiles {:uberjar {:aot :all}})

Zdrojový kód souboru src/git_test8/core.clj:

(ns git-test8.core
    (:gen-class))
 
(require '[clj-jgit.porcelain :as jgit])
(require '[clj-jgit.querying  :as jgit-query])
(require '[hozumi.rm-rf :as rm-rf])
 
(def repository-url
    "Adresa GIT repositare vcetne specifikace protokolu."
    "https://github.com/tisnik/testrepo.git")
 
(def directory-name
    "Jmeno adresare, do ktereho se GIT repositar naklonuje."
    "repo")
 
(defn clone-repository
    "Naklonovani GIT repositare do specifikovaneho adresare."
    [url directory]
    (jgit/git-clone url directory))
 
(defn delete-directory
    "Smazani adresare vcetne podadresaru a souboru."
    [directory]
    (rm-rf/rm-r (java.io.File. directory)))
 
(defn print-customized-log
    "Vypis logovacich informaci ve zvolenem formatu."
    [repository]
    (println "\nLog:")
    (doseq [log-entry (jgit/git-log repository)]
        (let [info (jgit-query/commit-info repository log-entry)]
             (println (:author info) ":" (:message info)))))
 
(defn print-local-branches
    "Vypis vsech lokalnich vetvi pro vybrany repositar."
    [repo]
    (println "\nLocal branches")
    (doseq [branch (jgit/git-branch-list repo)]
        (println (.getName branch))))
 
(defn print-remote-branches
    "Vypis vsech vzdalenych vetvi pro vybrany repositar."
    [repo]
    (println "\nRemote branches")
    (doseq [branch (jgit/git-branch-list repo :remote)]
        (println (.getName branch))))
 
(defn git-test-8
    "Naklonovani repositare, nacteni informaci
     z vytvoreneho adresare a vypis podrobnejsiho logu."
    [repository-url directory-name]
    ; naklonovani repositare do specifikovaneho adresare
    (clone-repository repository-url directory-name)
    ; nacteni informaci o repositari z lokalniho adresare
    ; povsimnete si pouziti "automagicky" vytvorene promenne,
    ; ktera se jmenuje 'repo'
    (try (jgit/with-repo directory-name
                         (print-customized-log repo)
                         (print-local-branches repo)
                         (print-remote-branches repo))
         (finally
             ; vymazani adresare s naklonovanym repositarem
             (delete-directory directory-name))))
 
(defn -main
    "Funkce zavolana po zadani prikazu 'lein run'."
    [& args]
    (git-test-8 repository-url directory-name))

Po spuštění druhého demonstračního příkladu nad testovacím repositářem by se měly na standardní výstup vypsat následující informace:

Log:
Pavel Tisnovsky : Added garbage
Pavel Tisnovsky : Updated README.md
Pavel Tišnovský : Initial commit
 
Local branches
refs/heads/master
 
Remote branches
refs/remotes/origin/branch-1
refs/remotes/origin/branch-2
refs/remotes/origin/master

4. Demonstrační příklad git-test9: přepnutí na vybranou větev (checkout)

Získání sekvence lokálních či vzdálených větví je samozřejmě pouze nezbytný začátek pro provádění dalších operací s větvemi. Pro přepnutí větví se v GITu používá příkaz git checkout [jméno větve] a podobně nazvaná funkce – clj-jgit.porcelain/git-checkout – je samozřejmě součástí knihovny clj-jgit. Deklarace této funkce vypadá poněkud složitě, ale to jen z toho důvodu, že mnoho jejích parametrů je nepovinných:

(defn git-checkout
  ([^Git repo branch-name]
     (git-checkout repo branch-name false false nil))
  ([^Git repo branch-name create-branch?]
     (git-checkout repo branch-name create-branch? false nil))
  ([^Git repo branch-name create-branch? force?]
     (git-checkout repo branch-name create-branch? force? nil))
  ([^Git repo branch-name create-branch? force? ^String start-point]
     (if (nil? start-point)
       (-> repo
           (.checkout)
           (.setName branch-name)
           (.setCreateBranch create-branch?)
           (.setForce force?)
           (.call))
       (-> repo
           (.checkout)
           (.setName branch-name)
           (.setCreateBranch create-branch?)
           (.setForce force?)
           (.setStartPoint start-point)
           (.call)))))

V našem demonstračním příkladu bude použita první (nejjednodušší) možnost volání této funkce, kdy se jí předá pouze reference na repositář a jméno větve:

(defn checkout
    [repo branch-name]
    (try
        (jgit/git-checkout repo branch-name)
        (catch Exception e
            (println "Unable to checkout: " e))))
 
 
 
(checkout repo "refs/remotes/origin/branch-1")

Vytvoření kostry demonstračního příkladu:

lein new app git-9

Úprava projektového souboru project.clj se nijak neliší od předchozích příkladů:

(defproject git-test9 "0.1.0-SNAPSHOT"
    :description "FIXME: write description"
    :url "http://example.com/FIXME"
    :license {:name "Eclipse Public License"
              :url "http://www.eclipse.org/legal/epl-v10.html"}
    :dependencies [[org.clojure/clojure "1.6.0"]
                   [clj-jgit "0.8.0"]
                   [clj-rm-rf "1.0.0-SNAPSHOT"]]
    :main ^:skip-aot git-test9.core
    :target-path "target/%s"
    :profiles {:uberjar {:aot :all}})

Zdrojový kód souboru src/git_test9/core.clj:

(ns git-test9.core
    (:gen-class))
 
(require '[clj-jgit.porcelain :as jgit])
(require '[clj-jgit.querying  :as jgit-query])
(require '[hozumi.rm-rf :as rm-rf])
 
(def repository-url
    "Adresa GIT repositare vcetne specifikace protokolu."
    "https://github.com/tisnik/testrepo.git")
 
(def directory-name
    "Jmeno adresare, do ktereho se GIT repositar naklonuje."
    "repo")
 
(defn clone-repository
    "Naklonovani GIT repositare do specifikovaneho adresare."
    [url directory]
    (jgit/git-clone url directory))
 
(defn delete-directory
    "Smazani adresare vcetne podadresaru a souboru."
    [directory]
    (rm-rf/rm-r (java.io.File. directory)))
 
(defn print-customized-log
    "Vypis logovacich informaci ve zvolenem formatu."
    [repository]
    (println "\nLog:")
    (doseq [log-entry (jgit/git-log repository)]
        (let [info (jgit-query/commit-info repository log-entry)]
             (println (:author info) ":" (:message info)))))
 
(defn print-local-branches
    "Vypis vsech lokalnich vetvi pro vybrany repositar."
    [repo]
    (println "\nLocal branches")
    (doseq [branch (jgit/git-branch-list repo)]
        (println (.getName branch))))
 
(defn print-remote-branches
    "Vypis vsech vzdalenych vetvi pro vybrany repositar."
    [repo]
    (println "\nRemote branches")
    (doseq [branch (jgit/git-branch-list repo :remote)]
        (println (.getName branch))))
 
(defn checkout
    [repo branch-name]
    (try
        (jgit/git-checkout repo branch-name)
        (catch Exception e
            (println "Unable to checkout: " e))))
 
(defn git-test-9
    "Naklonovani repositare, nacteni informaci
     z vytvoreneho adresare a vypis podrobnejsiho logu."
    [repository-url directory-name]
    ; naklonovani repositare do specifikovaneho adresare
    (clone-repository repository-url directory-name)
    ; nacteni informaci o repositari z lokalniho adresare
    ; povsimnete si pouziti "automagicky" vytvorene promenne,
    ; ktera se jmenuje 'repo'
    (try (jgit/with-repo directory-name
                         (print-customized-log repo)
                         (print-local-branches repo)
                         (print-remote-branches repo)
                         (checkout repo "refs/remotes/origin/branch-1")
                         (print-local-branches repo)
                         (print-remote-branches repo))
         (finally
             ; vymazani adresare s naklonovanym repositarem
             (delete-directory directory-name))))
 
(defn -main
    "Funkce zavolana po zadani prikazu 'lein run'."
    [& args]
    (git-test-9 repository-url directory-name))

Zajímavé informace se vypíšou na standardní výstup po spuštění tohoto příkladu. První část výpisu se vztahuje k lokálním a globálním větvím ve chvíli, než je proveden checkout:

Log:
Pavel Tisnovsky : Added garbage
Pavel Tisnovsky : Updated README.md
Pavel Tišnovský : Initial commit
 
Local branches
refs/heads/master
 
Remote branches
refs/remotes/origin/branch-1
refs/remotes/origin/branch-2
refs/remotes/origin/master

Po provedení checkoutu dostaneme odlišné sekvence, což ovšem opět odpovídá chování GITu, viz též man git-checkout:

Local branches
HEAD
refs/heads/master
 
Remote branches
HEAD
refs/remotes/origin/branch-1
refs/remotes/origin/branch-2
refs/remotes/origin/master

Všechny další operace, tj. zejména minule popsané přidání souboru, ubrání (vymazání) souboru či modifikace souboru, se samozřejmě vztahují k aktuální větvi.

5. Demonstrační příklad git-test10: vytvoření nové (lokální) větve

Podívejme se nyní na další dvě základní operace, které lze provádět s větvemi. Pro vytvoření nové lokální větve slouží funkce clj-jgit.porcelain/git-branch-create, pro smazání pak funkce clj-jgit.porcelain/git-branch-delete. V nejjednodušším případě se těmto funkcím předává reference na repositáž a jméno větve, která se má nově vytvořit či naopak smazat; ovšem obě funkce mají i další nepovinné parametry, což je patrné z výpisu jejich zdrojového kódu (kde mimochodem je opět ukázáno elegantní obalení složitějšího javovského kódu):

(defn git-branch-create
  ([^Git repo branch-name]
     (git-branch-create repo branch-name false nil))
  ([^Git repo branch-name force?]
     (git-branch-create repo branch-name force? nil))
  ([^Git repo branch-name force? ^String start-point]
     (if (nil? start-point)
       (-> repo
           (.branchCreate)
           (.setName branch-name)
           (.setForce force?)
           (.call))
       (-> repo
           (.branchCreate)
           (.setName branch-name)
           (.setForce force?)
           (.setStartPoint start-point)
           (.call)))))
 
(defn git-branch-delete
  ([^Git repo branch-names]
     (git-branch-delete repo branch-names false))
  ([^Git repo branch-names force?]
     (-> repo
         (.branchDelete)
         (.setBranchNames (into-array String branch-names))
         (.setForce force?)
         (.call))))

Použití funkce clj-jgit.porcelain/git-branch-create je skutečně velmi jednoduché:

(jgit/git-branch-create repo "new-branch")

V dalším demonstračním příkladu bude ukázáno, jak se změní výpis lokálních a vzdálených větví po vytvoření nové větve, přepnutí na jinou větvi atd. Vytvoření kostry demonstračního příkladu:

lein new app git-10

Úprava projektového souboru project.clj (podle předpokladu se zde nedějí žádné podstatné změny):

(defproject git-test10 "0.1.0-SNAPSHOT"
    :description "FIXME: write description"
    :url "http://example.com/FIXME"
    :license {:name "Eclipse Public License"
              :url "http://www.eclipse.org/legal/epl-v10.html"}
    :dependencies [[org.clojure/clojure "1.6.0"]
                   [clj-jgit "0.8.0"]
                   [clj-rm-rf "1.0.0-SNAPSHOT"]]
    :main ^:skip-aot git-test10.core
    :target-path "target/%s"
    :profiles {:uberjar {:aot :all}})

Zdrojový kód souboru src/git_test10/core.clj:

(ns git-test10.core
    (:gen-class))
 
(require '[clj-jgit.porcelain :as jgit])
(require '[clj-jgit.querying  :as jgit-query])
(require '[hozumi.rm-rf :as rm-rf])
 
(def repository-url
    "Adresa GIT repositare vcetne specifikace protokolu."
    "https://github.com/tisnik/testrepo.git")
 
(def directory-name
    "Jmeno adresare, do ktereho se GIT repositar naklonuje."
    "repo")
 
(defn clone-repository
    "Naklonovani GIT repositare do specifikovaneho adresare."
    [url directory]
    (jgit/git-clone url directory))
 
(defn delete-directory
    "Smazani adresare vcetne podadresaru a souboru."
    [directory]
    (rm-rf/rm-r (java.io.File. directory)))
 
(defn print-customized-log
    "Vypis logovacich informaci ve zvolenem formatu."
    [repository]
    (println "\nLog:")
    (doseq [log-entry (jgit/git-log repository)]
        (let [info (jgit-query/commit-info repository log-entry)]
             (println (:author info) ":" (:message info)))))
 
(defn print-local-branches
    "Vypis vsech lokalnich vetvi pro vybrany repositar."
    [repo]
    (println "\nLocal branches")
    (doseq [branch (jgit/git-branch-list repo)]
        (println (.getName branch))))
 
(defn print-remote-branches
    "Vypis vsech vzdalenych vetvi pro vybrany repositar."
    [repo]
    (println "\nRemote branches")
    (doseq [branch (jgit/git-branch-list repo :remote)]
        (println (.getName branch))))
 
(defn print-branches
    [repo]
    (print-local-branches repo)
    (print-remote-branches repo))
 
(defn checkout
    [repo branch-name]
    (try
        (jgit/git-checkout repo branch-name)
        (catch Exception e
            (println "Unable to checkout: " e))))
 
(defn git-test-10
    "Naklonovani repositare, nacteni informaci
     z vytvoreneho adresare a vypis podrobnejsiho logu."
    [repository-url directory-name]
    ; naklonovani repositare do specifikovaneho adresare
    (clone-repository repository-url directory-name)
    ; nacteni informaci o repositari z lokalniho adresare
    ; povsimnete si pouziti "automagicky" vytvorene promenne,
    ; ktera se jmenuje 'repo'
    (try (jgit/with-repo directory-name
                         (print-customized-log repo)
                         (print-branches repo)
 
                         (println "\nCheckout to branch-1")
                         (checkout repo "refs/remotes/origin/branch-1")
                         (print-branches repo)
 
                         (println "\nCreating new branch")
                         (jgit/git-branch-create repo "new-branch")
                         (print-branches repo)
 
                         (println "\nCheckout to new branch")
                         (checkout repo "new-branch")
                         (print-branches repo))
         (finally
             ; vymazani adresare s naklonovanym repositarem
             (delete-directory directory-name))))
 
(defn -main
    "Funkce zavolana po zadani prikazu 'lein run'."
    [& args]
    (git-test-10 repository-url directory-name))

Texty vypisované tímto příkladem si rozdělíme na několik částí. Nejdříve se vypíšou nám již známé logovací informace, kde není nic nového:

Log:
Pavel Tisnovsky : Added garbage
Pavel Tisnovsky : Updated README.md
Pavel Tišnovský : Initial commit

Dále se ihned po naklonování vypíšou seznamy lokálních větví (v tomto případě jen jedné větve) a větví vzdálených:

 
Local branches
refs/heads/master
 
Remote branches
refs/remotes/origin/branch-1
refs/remotes/origin/branch-2
refs/remotes/origin/master

Následně se provede přepnutí na větev branch-1, takže se seznamy podle očekávání změní:

Checkout to branch-1
 
Local branches
HEAD
refs/heads/master
 
Remote branches
HEAD
refs/remotes/origin/branch-1
refs/remotes/origin/branch-2
refs/remotes/origin/master

Ve třetím kroku se vytvoří nová větev a opět dojde k očekávané změně:

Creating new branch
 
Local branches
HEAD
refs/heads/master
refs/heads/new-branch
 
Remote branches
HEAD
refs/remotes/origin/branch-1
refs/remotes/origin/branch-2
refs/remotes/origin/master

Je důležité si uvědomit, že vytvoření nové větve ještě neznamená, že se na ni GIT přepne. To se musí provést explicitně:

Checkout to new branch
 
Local branches
refs/heads/master
refs/heads/new-branch
 
Remote branches
refs/remotes/origin/branch-1
refs/remotes/origin/branch-2
refs/remotes/origin/master

6. Demonstrační příklad git-test11: zjištění vybraných konfiguračních voleb repositáře

V dnešním posledním příkladu si ukážeme způsob zjištění (přečtení) vybraných konfiguračních voleb, tj. o přibližnou obdobu příkazu git config –get [jméno]. Zde již situace není úplně jednoduchá, protože je nutné použít složitější postup, který jsem implementoval ve funkci get-config-option:

(defn get-config-option
    [repo x y z]
    (-> repo
        (.getRepository)
        (.getConfig)
        (.getString x y z)))

Typickým (a možná i nejčastějším) příkladem použití je přečtení URL vzdáleného repositáře. Na příkazové řádce lze použít:

git config --get remote.origin.url
git@github.com:tisnik/clojure-examples.git

V Clojure aplikaci namísto toho použijeme:

(get-config-option repo "remote" "origin" "url")

V příkladu se přečtou a zobrazí několik konfiguračních voleb:

(defn print-repo-configuration
    [repo]
    (println "GIT repo origin URL:  " (get-config-option repo "remote" "origin" "url"))
    (println "Remote origin fetch:  " (get-config-option repo "remote" "origin" "fetch"))
    (println "Branch master remote: " (get-config-option repo "branch" "master" "remote")))

Vytvoření kostry demonstračního příkladu:

lein new app git-11

Úprava projektového souboru project.clj:

(defproject git-test11 "0.1.0-SNAPSHOT"
    :description "FIXME: write description"
    :url "http://example.com/FIXME"
    :license {:name "Eclipse Public License"
              :url "http://www.eclipse.org/legal/epl-v10.html"}
    :dependencies [[org.clojure/clojure "1.6.0"]
                   [clj-jgit "0.8.0"]
                   [clj-rm-rf "1.0.0-SNAPSHOT"]]
    :main ^:skip-aot git-test11.core
    :target-path "target/%s"
    :profiles {:uberjar {:aot :all}})

Zdrojový kód souboru src/git_test11/core.clj:

(ns git-test11.core
    (:gen-class))
 
(require '[clj-jgit.porcelain :as jgit])
(require '[clj-jgit.querying  :as jgit-query])
(require '[hozumi.rm-rf :as rm-rf])
 
(def repository-url
    "Adresa GIT repositare vcetne specifikace protokolu."
    "https://github.com/tisnik/testrepo.git")
 
(def directory-name
    "Jmeno adresare, do ktereho se GIT repositar naklonuje."
    "repo")
 
(defn clone-repository
    "Naklonovani GIT repositare do specifikovaneho adresare."
    [url directory]
    (jgit/git-clone url directory))
 
(defn delete-directory
    "Smazani adresare vcetne podadresaru a souboru."
    [directory]
    (rm-rf/rm-r (java.io.File. directory)))
 
(defn get-config-option
    [repo x y z]
    (-> repo
        (.getRepository)
        (.getConfig)
        (.getString x y z)))
 
(defn print-repo-configuration
    [repo]
    (println "GIT repo origin URL:  " (get-config-option repo "remote" "origin" "url"))
    (println "Remote origin fetch:  " (get-config-option repo "remote" "origin" "fetch"))
    (println "Branch master remote: " (get-config-option repo "branch" "master" "remote")))
 
(defn git-test-11
    "Naklonovani repositare, nacteni informaci
     z vytvoreneho adresare a vypis podrobnejsiho logu."
    [repository-url directory-name]
    ; naklonovani repositare do specifikovaneho adresare
    (clone-repository repository-url directory-name)
    ; nacteni informaci o repositari z lokalniho adresare
    ; povsimnete si pouziti "automagicky" vytvorene promenne,
    ; ktera se jmenuje 'repo'
    (try (jgit/with-repo directory-name
                         (print-repo-configuration repo))
         (finally
             ; vymazani adresare s naklonovanym repositarem
             (delete-directory directory-name))))
 
(defn -main
    "Funkce zavolana po zadani prikazu 'lein run'."
    [& args]
    (git-test-11 repository-url directory-name))

Po spuštění tohoto demonstračního příkladu by se měly vypsat následující řádky (popř. nějaké chybové hlášení):

bitcoin_skoleni

GIT repo origin URL:   https://github.com/tisnik/testrepo.git
Remote origin fetch:   +refs/heads/*:refs/remotes/origin/*
Branch master remote:  origin

7. Repositář s dnešními demonstračními příklady

Všech pět dnes popsaných demonstračních příkladů bylo, podobně jako v předchozích částech tohoto seriálu, uloženo do Git repositáře dostupného na adrese https://github.com/tisnik/clojure-examples. V tabulce zobrazené pod tímto odstavcem naleznete na zdrojové kódy jednotlivých demonstračních příkladů přímé odkazy:

8. Odkazy na předchozí části seriálu

Stalo se již zvykem uvést odkazy na všechny předchozí části tohoto seriálu. Tento zvyk samozřejmě dodržíme i dnes:

  1. Leiningen: nástroj pro správu projektů napsaných v Clojure
    http://www.root.cz/clanky/leiningen-nastroj-pro-spravu-projektu-napsanych-v-clojure/
  2. Leiningen: nástroj pro správu projektů napsaných v Clojure (2)
    http://www.root.cz/clanky/leiningen-nastroj-pro-spravu-projektu-napsanych-v-clojure-2/
  3. Leiningen: nástroj pro správu projektů napsaných v Clojure (3)
    http://www.root.cz/clanky/leiningen-nastroj-pro-spravu-projektu-napsanych-v-clojure-3/
  4. Leiningen: nástroj pro správu projektů napsaných v Clojure (4)
    http://www.root.cz/clanky/leiningen-nastroj-pro-spravu-projektu-napsanych-v-clojure-4/
  5. Leiningen: nástroj pro správu projektů napsaných v Clojure (5)
    http://www.root.cz/clanky/leiningen-nastroj-pro-spravu-projektu-napsanych-v-clojure-5/
  6. Leiningen: nástroj pro správu projektů napsaných v Clojure (6)
    http://www.root.cz/clanky/leiningen-nastroj-pro-spravu-projektu-napsanych-v-clojure-6/
  7. Programovací jazyk Clojure a databáze (1.část)
    http://www.root.cz/clanky/programovaci-jazyk-clojure-a-databaze-1-cast/
  8. Pluginy pro Leiningen
    http://www.root.cz/clanky/leiningen-nastroj-pro-spravu-projektu-napsanych-v-clojure-pluginy-pro-leiningen/
  9. Programovací jazyk Clojure a knihovny pro práci s vektory a maticemi
    http://www.root.cz/clanky/programovaci-jazyk-clojure-a-knihovny-pro-praci-s-vektory-a-maticemi/
  10. Programovací jazyk Clojure a knihovny pro práci s vektory a maticemi (2)
    http://www.root.cz/clanky/programovaci-jazyk-clojure-a-knihovny-pro-praci-s-vektory-a-maticemi-2/
  11. Programovací jazyk Clojure: syntéza procedurálních textur s využitím knihovny Clisk
    http://www.root.cz/clanky/programovaci-jazyk-clojure-synteza-proceduralnich-textur-s-vyuzitim-knihovny-clisk/
  12. Programovací jazyk Clojure: syntéza procedurálních textur s využitím knihovny Clisk (2)
    http://www.root.cz/clanky/programovaci-jazyk-clojure-synteza-proceduralnich-textur-s-vyuzitim-knihovny-clisk-2/
  13. Programovací jazyk Clojure: syntéza procedurálních textur s využitím knihovny Clisk (dokončení)
    http://www.root.cz/clanky/programovaci-jazyk-clojure-synteza-proceduralnich-textur-s-vyuzitim-knihovny-clisk-dokonceni/
  14. Seesaw: knihovna pro snadnou tvorbu GUI v jazyce Clojure
    http://www.root.cz/clanky/seesaw-knihovna-pro-snadnou-tvorbu-gui-v-jazyce-clojure/
  15. Seesaw: knihovna pro snadnou tvorbu GUI v jazyce Clojure (2)
    http://www.root.cz/clanky/seesaw-knihovna-pro-snadnou-tvorbu-gui-v-jazyce-clojure-2/
  16. Seesaw: knihovna pro snadnou tvorbu GUI v jazyce Clojure (3)
    http://www.root.cz/clanky/seesaw-knihovna-pro-snadnou-tvorbu-gui-v-jazyce-clojure-3/
  17. Programovací jazyk Clojure a práce s Gitem
    http://www.root.cz/clanky/programovaci-jazyk-clojure-a-prace-s-gitem/

9. Odkazy na Internetu

  1. Seriál o Gitu: 1. díl – Git – Historie a principy
    http://www.itnetwork.cz/git-tutorial-historie-a-principy
  2. 2. díl – Git – Instalace a vytvoření repositáře
    http://www.itnetwork.cz/git-tutorial-instalace-a-stazeni-repositare
  3. 3. díl – Git – Základy
    http://www.itnetwork.cz/git-tutorial-zaklady
  4. 4. díl – Git – Zkoumání historie
    http://www.itnetwork.cz/git-tutorial-historie
  5. 5. díl – Git – Rozděluj a panuj
    http://www.itnetwork.cz/git-tutorial-vetve
  6. 6. díl – Git – práce se vzdáleným repositářem
    http://www.itnetwork.cz/git-prace-se-vzdalenym-repositarem
  7. Building User Interfaces with Seesaw (slajdy k přednášce)
    http://darevay.com/talks/clo­jurewest2012/#/title-slide
  8. Seesaw na GitHubu
    https://github.com/daveray/seesaw
  9. Seesaw API Documentation
    http://daveray.github.io/seesaw/
  10. Seesaw wiki
    https://github.com/davera­y/seesaw/wiki
  11. seesaw-repl-tutorial.clj
    https://gist.github.com/da­veray/1441520
  12. Témata o Seesaw na Google groups
    https://groups.google.com/fo­rum/#!forum/seesaw-clj
  13. Threading macro (dokumentace k jazyku Clojure)
    https://clojure.github.io/clo­jure/clojure.core-api.html#clojure.core/->
  14. Understanding the Clojure → macro
    http://blog.fogus.me/2009/09/04/un­derstanding-the-clojure-macro/
  15. Clisk
    https://github.com/mikera/clisk
  16. clojars: net.mikera/clisk
    https://clojars.org/net.mikera/clisk
  17. clojure.inspector
    http://clojure.github.io/clo­jure/clojure.inspector-api.html
  18. Clisk: wiki
    https://github.com/mikera/clisk/wiki
  19. Dokumentace vygenerovaná pro knihovnu core.matrix
    https://cloojure.github.i­o/doc/core.matrix/index.html
  20. Size and Dimensionality
    https://groups.google.com/fo­rum/#!topic/numerical-clojure/zebBCa68eTw/discussion
  21. Towards core.matrix for Clojure?
    https://clojurefun.wordpres­s.com/2013/01/05/towards-core-matrix-for-clojure/
  22. The Clojure Toolbox
    http://www.clojure-toolbox.com/
  23. Neanderthal
    http://neanderthal.uncomplicate.org/
  24. Hello world project
    https://github.com/uncompli­cate/neanderthal/blob/mas­ter/examples/hello-world/project.clj
  25. vectorz-clj
    https://github.com/mikera/vectorz-clj
  26. vectorz – Examples
    https://github.com/mikera/vectorz-clj/wiki/Examples
  27. gloss
    https://github.com/ztellman/gloss
  28. HTTP client/server for Clojure
    http://www.http-kit.org/
  29. Array Programming
    https://en.wikipedia.org/wi­ki/Array_programming
  30. Discovering Array Languages
    http://archive.vector.org­.uk/art10008110
  31. no stinking loops – Kalothi
    http://www.nsl.com/
  32. Vector (obsahuje odkazy na články, knihy a blogy o programovacích jazycích APL, J a K)
    http://www.vector.org.uk/
  33. APL Interpreters
    http://www.vector.org.uk/?a­rea=interpreters
  34. APL_(programming_language
    http://en.wikipedia.org/wi­ki/APL_(programming_langu­age
  35. APL FAQ
    http://www.faqs.org/faqs/apl-faq/
  36. APL FAQ (nejnovější verze)
    http://home.earthlink.net/~swsir­lin/apl.faq.html
  37. A+
    http://www.aplusdev.org/
  38. APLX
    http://www.microapl.co.uk/
  39. FreeAPL
    http://www.pyr.fi/apl/index.htm
  40. J: a modern, high-level, general-purpose, high-performance programming language
    http://www.jsoftware.com/
  41. K, Kdb: an APL derivative for Solaris, Linux, Windows
    http://www.kx.com
  42. openAPL (GPL)
    http://sourceforge.net/pro­jects/openapl
  43. Parrot APL (GPL)
    http://www.parrotcode.org/
  44. Learning J (Roger Stokes)
    http://www.jsoftware.com/hel­p/learning/contents.htm
  45. Rosetta Code
    http://rosettacode.org/wiki/Main_Page
  46. Why APL
    http://www.acm.org/sigapl/whyapl.htm
  47. java.jdbc API Reference
    https://clojure.github.io/java.jdbc/
  48. Hiccup
    https://github.com/weavejester/hiccup
  49. Clojure Ring na GitHubu
    https://github.com/ring-clojure/ring
  50. A brief overview of the Clojure web stack
    https://brehaut.net/blog/2011/rin­g_introduction
  51. Getting Started with Ring
    http://www.learningclojure­.com/2013/01/getting-started-with-ring.html
  52. Getting Started with Ring and Compojure – Clojure Web Programming
    http://www.myclojureadven­ture.com/2011/03/getting-started-with-ring-and-compojure.html
  53. Unit Testing in Clojure
    http://nakkaya.com/2009/11/18/unit-testing-in-clojure/
  54. Testing in Clojure (Part-1: Unit testing)
    http://blog.knoldus.com/2014/03/22/tes­ting-in-clojure-part-1-unit-testing/
  55. API for clojure.test – Clojure v1.6 (stable)
    https://clojure.github.io/clo­jure/clojure.test-api.html
  56. Leiningen: úvodní stránka
    http://leiningen.org/
  57. Leiningen: Git repository
    https://github.com/techno­mancy/leiningen
  58. leiningen-win-installer
    http://leiningen-win-installer.djpowell.net/
  59. Clojure 1: Úvod
    http://www.root.cz/clanky/clojure-aneb-jazyk-umoznujici-tvorbu-bezpecnych-vicevlaknovych-aplikaci-pro-jvm/
  60. Clojure 2: Symboly, kolekce atd.
    http://www.root.cz/clanky/clojure-aneb-jazyk-umoznujici-tvorbu-bezpecnych-vicevlaknovych-aplikaci-pro-jvm-2-cast/
  61. Clojure 3: Funkcionální programování
    http://www.root.cz/clanky/clojure-aneb-jazyk-umoznujici-tvorbu-bezpecnych-vicevlaknovych-aplikaci-pro-jvm-3-cast-funkcionalni-programovani/
  62. Clojure 4: Kolekce, sekvence a lazy sekvence
    http://www.root.cz/clanky/clojure-aneb-jazyk-umoznujici-tvorbu-bezpecnych-vicevlaknovych-aplikaci-pro-jvm-4-cast-kolekce-sekvence-a-lazy-sekvence/
  63. Clojure 5: Sekvence, lazy sekvence a paralelní programy
    http://www.root.cz/clanky/clojure-a-bezpecne-aplikace-pro-jvm-sekvence-lazy-sekvence-a-paralelni-programy/
  64. Clojure 6: Podpora pro paralelní programování
    http://www.root.cz/clanky/programovaci-jazyk-clojure-6-futures-nejsou-jen-financni-derivaty/
  65. Clojure 7: Další funkce pro paralelní programování
    http://www.root.cz/clanky/programovaci-jazyk-clojure-7-dalsi-podpurne-prostredky-pro-paralelni-programovani/
  66. Clojure 8: Identity, stavy, neměnné hodnoty a reference
    http://www.root.cz/clanky/programovaci-jazyk-clojure-8-identity-stavy-nemenne-hodnoty-a-referencni-typy/
  67. Clojure 9: Validátory, pozorovatelé a kooperace s Javou
    http://www.root.cz/clanky/programovaci-jazyk-clojure-9-validatory-pozorovatele-a-kooperace-mezi-clojure-a-javou/
  68. Clojure 10: Kooperace mezi Clojure a Javou
    http://www.root.cz/clanky/programovaci-jazyk-clojure-10-kooperace-mezi-clojure-a-javou-pokracovani/
  69. Clojure 11: Generátorová notace seznamu/list comprehension
    http://www.root.cz/clanky/programovaci-jazyk-clojure-11-generatorova-notace-seznamu-list-comprehension/
  70. Clojure 12: Překlad programů z Clojure do bajtkódu JVM I:
    http://www.root.cz/clanky/programovaci-jazyk-clojure-12-preklad-programu-z-clojure-do-bajtkodu-jvm/
  71. Clojure 13: Překlad programů z Clojure do bajtkódu JVM II:
    http://www.root.cz/clanky/programovaci-jazyk-clojure-13-preklad-programu-z-clojure-do-bajtkodu-jvm-pokracovani/
  72. Clojure 14: Základy práce se systémem maker
    http://www.root.cz/clanky/programovaci-jazyk-clojure-14-zaklady-prace-se-systemem-maker/
  73. Clojure 15: Tvorba uživatelských maker
    http://www.root.cz/clanky/programovaci-jazyk-clojure-15-tvorba-uzivatelskych-maker/
  74. Clojure 16: Složitější uživatelská makra
    http://www.root.cz/clanky/programovaci-jazyk-clojure-16-slozitejsi-uzivatelska-makra/
  75. Clojure 17: Využití standardních maker v praxi
    http://www.root.cz/clanky/programovaci-jazyk-clojure-17-vyuziti-standardnich-maker-v-praxi/
  76. Clojure 18: Základní techniky optimalizace aplikací
    http://www.root.cz/clanky/programovaci-jazyk-clojure-18-zakladni-techniky-optimalizace-aplikaci/
  77. Clojure 19: Vývojová prostředí pro Clojure
    http://www.root.cz/clanky/programovaci-jazyk-clojure-19-vyvojova-prostredi-pro-clojure/
  78. Clojure 20: Vývojová prostředí pro Clojure (Vimu s REPL)
    http://www.root.cz/clanky/programovaci-jazyk-clojure-20-vyvojova-prostredi-pro-clojure-integrace-vimu-s-repl/
  79. Clojure 21: ClojureScript aneb překlad Clojure do JS
    http://www.root.cz/clanky/programovaci-jazyk-clojure-21-clojurescript-aneb-preklad-clojure-do-javascriptu/

Autor článku

Vystudoval VUT FIT a v současné době pracuje na projektech vytvářených v jazycích Python a Go.