aboutsummaryrefslogtreecommitdiffstats
path: root/gitto/config.scm
blob: 5459d84204ca1d8a06b9a9e82d1701e7ef9b4d4a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
;; -*- coding: utf-8; -*-
;; gitto -- Keep track of your git repositories
;; Copyright (C) 2012 Tom Willemse <tom at ryuslash dot org>

;; This file is part of gitto.

;; gitto is free software: you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
;; the Free Software Foundation, either version 3 of the License, or
;; (at your option) any later version.

;; gitto is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
;; GNU General Public License for more details.

;; You should have received a copy of the GNU General Public License
;; along with gitto.  If not, see <http://www.gnu.org/licenses/>.

(define-module (gitto config)
  #:use-module (ice-9 format)
  #:use-module (ice-9 rdelim)
  #:export (global-config
            hook-alist

            install-hooks
            merge-config
            read-config
            write-config))

(define global-config '())
(define hook-alist '())

(define (install-hooks repo-location)
  (for-each
   (lambda (hook)
     (let ((new-name (string-append repo-location "/.git/hooks/"
                                    (car hook))))
       (unless (file-exists? new-name)
         (symlink (cdr hook) new-name))))
   hook-alist))

(define (merge-config repo-name x y)
  (let ((lst (if x (list-copy x) '())))
    (for-each
     (lambda (s)
       (let ((b-sec (assoc (car s) lst)))
        (set! lst (assoc-set!
                   lst (car s) (merge-settings
                                repo-name (if b-sec (cdr b-sec) #f) (cdr s))))))
     y)
    lst))

(define (merge-setting repo-name lst var val)
  (if (list? val)
      (assoc-set! lst var (map (lambda (v) (format #f v repo-name)) val))
      (assoc-set! lst var (format #f val repo-name))))

(define (merge-settings repo-name x y)
  (let ((lst (if x (list-copy x) '())))
    (for-each
     (lambda (v)
       (set! lst (merge-setting repo-name lst (car v) (cdr v))))
     y)
    lst))

(define (split-setting line)
  (let ((idx (string-index line #\=)))
    (cons (string-trim-both (substring line 0 idx))
          (string-trim-both (substring line (1+ idx))))))

(define (read-setting settings line)
  (let* ((new-setting (split-setting line))
         (var (car new-setting)) (val (cdr new-setting))
         (current-value (assoc-ref settings var)))
    (if current-value
        (if (list? current-value)
            (assoc-set! settings var (append current-value (list val)))
            (assoc-set! settings var (list current-value val)))
        (assoc-set! settings var val))))

(define (read-config repo-location)
  (let ((port (open-input-file
               (string-append repo-location "/.git/config")))
        (config '())
        (current-section #f))
    (do ((line (read-line port) (read-line port)))
        ((eof-object? line))
      (cond ((string= line "[" 0 1)
             (let ((section (cons (string-trim-both
                                   line (char-set #\[ #\])) '())))
               (set! config (append config (list section)))
               (set! current-section section)))
            ((string-contains line "=")
             (set-cdr! current-section
                       (read-setting (cdr current-section) line)))))
    (close-port port)
    config))

(define* (write-config config #:optional (file #f))
  (let ((thunk (lambda () (for-each write-section config))))
    (if file
        (with-output-to-file file thunk)
        (thunk))))

(define (write-section section)
  (format #t "[~a]~%" (car section))
  (for-each write-setting (cdr section)))

(define (write-setting setting)
  (let ((value (cdr setting)))
    (if (list? value)
        (map (lambda (v)
               (format #t "~8t~a = ~a~%" (car setting) v)) value)
        (format #t "~8t~a = ~a~%" (car setting) (cdr setting)))))