gitile/gitile/repo.scm

repo.scm

1
;;;; Copyright (C) 2020 Julien Lepiller <julien@lepiller.eu>
2
;;;;
3
;;;; This library is free software; you can redistribute it and/or
4
;;;; modify it under the terms of the GNU Lesser General Public
5
;;;; License as published by the Free Software Foundation; either
6
;;;; version 3 of the License, or (at your option) any later version.
7
;;;;
8
;;;; This library is distributed in the hope that it will be useful,
9
;;;; but WITHOUT ANY WARRANTY; without even the implied warranty of
10
;;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11
;;;; Lesser General Public License for more details.
12
;;;;
13
;;;; You should have received a copy of the GNU Lesser General Public
14
;;;; License along with this library; if not, write to the Free Software
15
;;;; Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
16
;;;;
17
18
(define-module (gitile repo)
19
  #:use-module (git)
20
  #:use-module (git types)
21
  #:use-module (gitile git)
22
  #:use-module (srfi srfi-9)
23
  #:use-module (system foreign)
24
  #:export (get-branches
25
            get-tags
26
            get-files
27
            get-file-content
28
            get-commits
29
            get-commit
30
            get-description
31
            last-commit
32
33
            <file>
34
            make-file
35
            file?
36
            file-name
37
            file-type))
38
39
(define tree-entry-type
40
  (let ((proc (libgit2->procedure int "git_tree_entry_type" '(*))))
41
    (lambda (entry)
42
      (proc (tree-entry->pointer entry)))))
43
44
(define (get-branches repo)
45
  (map (lambda (ref) (cons (reference-shorthand ref) (reference-name ref)))
46
       (filter reference-branch? (reference-fold cons '() repo))))
47
48
(define (get-tags repo)
49
  (map (lambda (ref) (cons (reference-shorthand ref) (reference-name ref)))
50
       (filter reference-tag? (reference-fold cons '() repo))))
51
52
(define (search-reference repo name)
53
  (reference-fold (lambda (ref acc)
54
                    (if (equal? name (reference-shorthand ref))
55
                        (reference-name ref)
56
                        acc))
57
                  #f
58
                  repo))
59
60
(define (ref->oid repo ref)
61
  (let ((ref-name (or ref
62
                      (false-if-exception (reference-name (repository-head repo))))))
63
    (or (false-if-exception (string->oid ref-name))
64
        (false-if-exception (reference-name->oid repo ref-name))
65
        (reference-name->oid repo (search-reference repo ref-name)))))
66
67
(define-record-type <file>
68
  (make-file name type commit)
69
  file?
70
  (name   file-name)
71
  (type   file-type)
72
  (commit file-commit))
73
74
(define* (get-files repo #:key (path "") (ref #f))
75
  (let* ((oid (ref->oid repo ref))
76
         (commit (commit-lookup repo oid))
77
         (tree (commit-tree commit)))
78
    (let ((result '()))
79
      (tree-walk
80
        tree TREEWALK-PRE
81
        (lambda (root entry)
82
          (when (equal? root path)
83
            (set! result
84
              (cons (make-file (tree-entry-name entry)
85
                               (tree-entry-type entry)
86
                               (last-commit-for-file
87
                                 (string-append root (tree-entry-name entry))
88
                                 commit))
89
                    result)))
90
          0))
91
      result)))
92
93
(define (last-commit repo ref)
94
  (let ((oid (ref->oid repo ref)))
95
    (commit-lookup repo oid)))
96
97
(define* (get-file-content repo path #:key (ref #f))
98
  (let* ((oid (ref->oid repo ref))
99
         (commit (commit-lookup repo oid))
100
         (tree (commit-tree commit))
101
         (entry (tree-entry-bypath tree path))
102
         (entry-oid (tree-entry-id entry))
103
         (blob (blob-lookup repo entry-oid)))
104
    (blob-content blob)))
105
106
(define (last-commit-for-file path commit)
107
  (let* ((initial-tree (commit-tree commit))
108
         (initial-entry (false-if-exception (tree-entry-bypath initial-tree path))))
109
    (let loop ((commit commit))
110
      (let ((pcommit (false-if-exception (commit-parent commit))))
111
        (if pcommit
112
            (let* ((ptree (commit-tree pcommit))
113
                   (pentry (false-if-exception (tree-entry-bypath ptree path))))
114
              (if (or (and (not initial-entry) (not pentry))
115
                      (and initial-entry pentry
116
                           (equal? (tree-entry-id initial-entry)
117
                                   (tree-entry-id pentry))))
118
                  (loop pcommit)
119
                  commit))
120
            commit)))))
121
122
(define (get-commits repo ref)
123
  (let* ((oid (ref->oid repo ref))
124
         (commit (commit-lookup repo oid)))
125
    (let loop ((result (list commit)) (commit commit))
126
      (let ((pcommit (false-if-exception (commit-parent commit))))
127
        (if (and pcommit (< (length result) 20))
128
            (loop (cons pcommit result) pcommit)
129
            (cons (reverse result) pcommit))))))
130
131
(define (get-options config)
132
  (let ((out '()))
133
    (config-foreach
134
      config
135
      (lambda (entry)
136
        (set! out (cons (cons (config-entry-name entry)
137
                              (config-entry-value entry))
138
                        out))
139
        0))
140
    out))
141
142
(define (get-description repo)
143
  (let* ((config (repository-config repo))
144
         (options (get-options config)))
145
    (or (assoc-ref options "gitweb.description") "")))
146
147
(define (get-commit repo hash)
148
  (let* ((oid (ref->oid repo hash))
149
         (commit (commit-lookup repo oid)))
150
    commit))
151