diff options
author | Arun Isaac | 2022-06-23 19:07:46 +0530 |
---|---|---|
committer | Arun Isaac | 2022-06-23 19:07:46 +0530 |
commit | 76d9a3a7c7b2d86060670b3a53210bad66dbc3c8 (patch) | |
tree | 6de76b9cee3a273d14ac1214f394e8f3f67868fc /tissue/git.scm | |
parent | 49163adccd8ca1b60192dd54770e3525f1a2ad97 (diff) | |
download | tissue-76d9a3a7c7b2d86060670b3a53210bad66dbc3c8.tar.gz tissue-76d9a3a7c7b2d86060670b3a53210bad66dbc3c8.tar.lz tissue-76d9a3a7c7b2d86060670b3a53210bad66dbc3c8.zip |
issue: Lookup commits affecting file using guile-git.
* tissue/git.scm: Import (rnrs hashtables) and (ice-9 match).
(commit-deltas): New function.
(file-modification-table): New public function.
* tissue/issue.scm: Import (git).
(file-details): Do not lookup git history for file using `git log'.
(issues): Use file-modification-table to lookup git history.
Diffstat (limited to 'tissue/git.scm')
-rw-r--r-- | tissue/git.scm | 56 |
1 files changed, 55 insertions, 1 deletions
diff --git a/tissue/git.scm b/tissue/git.scm index 4b7f7c7..fcfc6c7 100644 --- a/tissue/git.scm +++ b/tissue/git.scm @@ -18,11 +18,13 @@ (define-module (tissue git) #:use-module (rnrs arithmetic bitwise) + #:use-module (rnrs hashtables) #:use-module (rnrs io ports) #:use-module (srfi srfi-9) #:use-module (srfi srfi-19) #:use-module (srfi srfi-26) #:use-module (srfi srfi-171) + #:use-module (ice-9 match) #:use-module (git) #:use-module (git types) ;; There are many name conflicts between (system foreign). So, we @@ -42,7 +44,8 @@ #:export (git-top-level current-git-repository commit-date - git-tracked-files)) + git-tracked-files + file-modification-table)) ;; We bind additional functions from libgit2 that are not already ;; bound in guile-git. TODO: Contribute them to guile-git. @@ -197,3 +200,54 @@ filenames are relative to the top-level directory of REPOSITORY and do not have a leading slash." (map index-entry-path (index-entries (repository-index repository)))) + +(define (commit-deltas repository commit) + "Return the list of <diff-delta> objects created by COMMIT with +respect to its first parent in REPOSITORY." + (match (commit-parents commit) + ((parent _ ...) + (let ((diff (diff-tree-to-tree repository + (commit-tree parent) + (commit-tree commit)))) + (diff-find-similar! diff) + (diff-fold (lambda (delta progress result) + (cons delta result)) + (lambda (delta binary result) + result) + (lambda (delta hunk result) + result) + (lambda (delta hunk line result) + result) + (list) + diff))) + (() (list)))) + +(define (file-modification-table repository) + "Return a hashtable mapping files to the list of commits in REPOSITORY +that modified them." + (let ((result (make-hashtable string-hash string=?)) + (renames (make-hashtable string-hash string=?))) + (fold-commits + (lambda (commit _) + (map (lambda (delta) + ;; Map old filename to current filename if they are + ;; different. Note that this manner of following renames + ;; requires a linear git history and will not work with + ;; branch merges. + (unless (string=? (diff-file-path (diff-delta-old-file delta)) + (diff-file-path (diff-delta-new-file delta))) + (hashtable-set! renames + (diff-file-path (diff-delta-old-file delta)) + (diff-file-path (diff-delta-new-file delta)))) + (hashtable-update! result + ;; If necessary, translate old + ;; filename to current filename. + (hashtable-ref renames + (diff-file-path (diff-delta-old-file delta)) + (diff-file-path (diff-delta-old-file delta))) + (cut cons commit <>) + (list))) + (commit-deltas repository commit))) + #f + repository) + result)) |