Blame


1 406d7b4d 2020-12-26 op ;;; vc-got.el --- Game of Tree backend for VC -*- lexical-binding: t; -*-
2 af5ef7cd 2020-11-29 op
3 406d7b4d 2020-12-26 op ;; Copyright (C) 2020 Omar Polo
4 af5ef7cd 2020-11-29 op
5 406d7b4d 2020-12-26 op ;; Author: Omar Polo <op@venera>
6 406d7b4d 2020-12-26 op ;; Keywords: vc
7 af5ef7cd 2020-11-29 op
8 406d7b4d 2020-12-26 op ;; This program is free software; you can redistribute it and/or modify
9 406d7b4d 2020-12-26 op ;; it under the terms of the GNU General Public License as published by
10 406d7b4d 2020-12-26 op ;; the Free Software Foundation, either version 3 of the License, or
11 406d7b4d 2020-12-26 op ;; (at your option) any later version.
12 af5ef7cd 2020-11-29 op
13 406d7b4d 2020-12-26 op ;; This program is distributed in the hope that it will be useful,
14 406d7b4d 2020-12-26 op ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
15 406d7b4d 2020-12-26 op ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 406d7b4d 2020-12-26 op ;; GNU General Public License for more details.
17 af5ef7cd 2020-11-29 op
18 406d7b4d 2020-12-26 op ;; You should have received a copy of the GNU General Public License
19 406d7b4d 2020-12-26 op ;; along with this program. If not, see <https://www.gnu.org/licenses/>.
20 406d7b4d 2020-12-26 op
21 af5ef7cd 2020-11-29 op ;;; Commentary
22 af5ef7cd 2020-11-29 op
23 af5ef7cd 2020-11-29 op ;; Backend implementation status
24 af5ef7cd 2020-11-29 op ;;
25 af5ef7cd 2020-11-29 op ;; Function marked with `*' are required, those with `-' are optional.
26 af5ef7cd 2020-11-29 op ;;
27 af5ef7cd 2020-11-29 op ;; FUNCTION NAME STATUS
28 af5ef7cd 2020-11-29 op ;;
29 af5ef7cd 2020-11-29 op ;; BACKEND PROPERTIES:
30 af5ef7cd 2020-11-29 op ;; * revision-granularity DONE
31 af5ef7cd 2020-11-29 op ;; - update-on-retrieve-tag XXX: what should this do?
32 af5ef7cd 2020-11-29 op ;;
33 af5ef7cd 2020-11-29 op ;; STATE-QUERYING FUNCTIONS:
34 af5ef7cd 2020-11-29 op ;; * registered DONE
35 af5ef7cd 2020-11-29 op ;; * state DONE
36 af5ef7cd 2020-11-29 op ;; - dir-status-files DONE
37 a8466f02 2020-12-07 op ;; - dir-extra-headers DONE
38 af5ef7cd 2020-11-29 op ;; - dir-printer NOT IMPLEMENTED
39 af5ef7cd 2020-11-29 op ;; - status-fileinfo-extra NOT IMPLEMENTED
40 af5ef7cd 2020-11-29 op ;; * working-revision DONE
41 af5ef7cd 2020-11-29 op ;; * checkout-model DONE
42 694534b4 2020-12-05 op ;; - mode-line-string DONE
43 23a0b465 2020-11-30 op ;;
44 23a0b465 2020-11-30 op ;; STATE-CHANGING FUNCTIONS:
45 23a0b465 2020-11-30 op ;; * create-repo NOT IMPLEMENTED
46 eb85ad27 2020-12-05 op ;; I don't think got init does what this function is supposed to
47 eb85ad27 2020-12-05 op ;; do.
48 23a0b465 2020-11-30 op ;; * register DONE
49 23a0b465 2020-11-30 op ;; - responsible-p DONE
50 23a0b465 2020-11-30 op ;; - receive-file NOT IMPLEMENTED
51 23a0b465 2020-11-30 op ;; - unregister NOT IMPLEMENTED
52 eb85ad27 2020-12-05 op ;; use remove?
53 23a0b465 2020-11-30 op ;; * checkin DONE
54 23a0b465 2020-11-30 op ;; * find-revision DONE
55 eb85ad27 2020-12-05 op ;; * checkout NOT IMPLEMENTED
56 eb85ad27 2020-12-05 op ;; I'm not sure how to properly implement this. Does filling
57 eb85ad27 2020-12-05 op ;; FILE with the find-revision do the trick? Or use got update?
58 eb85ad27 2020-12-05 op ;; * revert DONE
59 eb85ad27 2020-12-05 op ;; - merge-file NOT IMPLEMENTED
60 eb85ad27 2020-12-05 op ;; - merge-branch DONE
61 eb85ad27 2020-12-05 op ;; - merge-news NOT IMPLEMENTED
62 eb85ad27 2020-12-05 op ;; - pull DONE
63 686eac9a 2020-12-07 op ;; - push DONE
64 686eac9a 2020-12-07 op ;; uses git
65 eb85ad27 2020-12-05 op ;; - steal-lock NOT IMPLEMENTED
66 eb85ad27 2020-12-05 op ;; - modify-change-comment NOT IMPLEMENTED
67 eb85ad27 2020-12-05 op ;; can be implemented via histedit, if I understood correctly
68 eb85ad27 2020-12-05 op ;; what it is supposed to do.
69 eb85ad27 2020-12-05 op ;; - mark-resolved NOT IMPLEMENTED
70 eb85ad27 2020-12-05 op ;; - find-admin-dir NOT IMPLEMENTED
71 eb85ad27 2020-12-05 op ;;
72 eb85ad27 2020-12-05 op ;; HISTORY FUNCTIONS
73 eb85ad27 2020-12-05 op ;; * print-log DONE
74 9ad1eb5d 2020-12-07 op ;; * log-outgoing DONE
75 6eda2f1f 2020-12-26 op ;; * log-incoming DONE
76 eb85ad27 2020-12-05 op ;; - log-search DONE
77 eb85ad27 2020-12-05 op ;; - log-view-mode NOT IMPLEMENTED
78 6eda2f1f 2020-12-26 op ;; - show-log-entry NOT IMPLEMENTED
79 6eda2f1f 2020-12-26 op ;; - comment-history NOT IMPLEMENTED
80 6eda2f1f 2020-12-26 op ;; - update-changelog NOT IMPLEMENTED
81 af5ef7cd 2020-11-29 op
82 af5ef7cd 2020-11-29 op ;; TODO: use the idiom
83 af5ef7cd 2020-11-29 op ;; (let (process-file-side-effects) ...)
84 af5ef7cd 2020-11-29 op ;; when the got command WON'T change the file. This can enable some
85 af5ef7cd 2020-11-29 op ;; emacs optimizations
86 af5ef7cd 2020-11-29 op
87 eb85ad27 2020-12-05 op ;; TODO: vc-git has most function that starts with:
88 eb85ad27 2020-12-05 op ;;
89 eb85ad27 2020-12-05 op ;; (let* ((root (vc-git-root default-directory))
90 eb85ad27 2020-12-05 op ;; (buffer (format "*vc-git : %s*" (expand-file-name root)))
91 eb85ad27 2020-12-05 op ;; ...)
92 eb85ad27 2020-12-05 op ;; ...)
93 eb85ad27 2020-12-05 op ;;
94 eb85ad27 2020-12-05 op ;; we should 1) investigate if also other backends do something like
95 eb85ad27 2020-12-05 op ;; this (or if there is a better way) and 2) try to do the same.
96 eb85ad27 2020-12-05 op
97 af5ef7cd 2020-11-29 op ;;; Code:
98 af5ef7cd 2020-11-29 op
99 af5ef7cd 2020-11-29 op (eval-when-compile
100 af5ef7cd 2020-11-29 op (require 'subr-x))
101 af5ef7cd 2020-11-29 op
102 af5ef7cd 2020-11-29 op (require 'cl-lib)
103 518ede14 2020-12-05 op (require 'cl-seq)
104 af5ef7cd 2020-11-29 op (require 'seq)
105 23a0b465 2020-11-30 op (require 'vc)
106 af5ef7cd 2020-11-29 op
107 ba123905 2020-12-08 op (require 'vc-got-stage)
108 ba123905 2020-12-08 op
109 af5ef7cd 2020-11-29 op (defvar vc-got-cmd "got"
110 af5ef7cd 2020-11-29 op "The got command.")
111 af5ef7cd 2020-11-29 op
112 12ca62f2 2020-12-26 op (defcustom vc-got-diff-switches t
113 12ca62f2 2020-12-26 op "String or list of strings specifying switches for Got diff under VC.
114 12ca62f2 2020-12-26 op If nil, use the value of `vc-diff-switches'. If t, use no switches."
115 12ca62f2 2020-12-26 op :type '(choice (const :tag "Unspecified" nil)
116 12ca62f2 2020-12-26 op (const :tag "None" t)
117 12ca62f2 2020-12-26 op (string :tag "Argument String")
118 12ca62f2 2020-12-26 op (repeat :tag "Argument List" :value ("") string)))
119 12ca62f2 2020-12-26 op
120 af5ef7cd 2020-11-29 op ;; helpers
121 af5ef7cd 2020-11-29 op
122 af5ef7cd 2020-11-29 op (defun vc-got-root (file)
123 af5ef7cd 2020-11-29 op "Return the work tree root for FILE, or nil."
124 f6e414a6 2020-11-30 op (or (vc-file-getprop file 'got-root)
125 f6e414a6 2020-11-30 op (vc-file-setprop file 'got-root (vc-find-root file ".got"))))
126 af5ef7cd 2020-11-29 op
127 af5ef7cd 2020-11-29 op (defmacro vc-got-with-worktree (file &rest body)
128 af5ef7cd 2020-11-29 op "Evaluate BODY in the work tree directory of FILE."
129 af5ef7cd 2020-11-29 op (declare (indent defun))
130 af5ef7cd 2020-11-29 op `(when-let (default-directory (vc-got-root ,file))
131 af5ef7cd 2020-11-29 op ,@body))
132 686eac9a 2020-12-07 op
133 686eac9a 2020-12-07 op (defun vc-got--repo-root ()
134 686eac9a 2020-12-07 op "Return the path to the repository root.
135 686eac9a 2020-12-07 op Assume `default-directory' is inside a got worktree."
136 686eac9a 2020-12-07 op (vc-got-with-worktree default-directory
137 686eac9a 2020-12-07 op (with-temp-buffer
138 686eac9a 2020-12-07 op (insert-file-contents ".got/repository")
139 686eac9a 2020-12-07 op (string-trim (buffer-string) nil "\n"))))
140 af5ef7cd 2020-11-29 op
141 af5ef7cd 2020-11-29 op (defun vc-got--call (&rest args)
142 af5ef7cd 2020-11-29 op "Call `vc-got-cmd' in the `default-directory' with ARGS and put the output in the current buffer."
143 af5ef7cd 2020-11-29 op (apply #'process-file vc-got-cmd nil (current-buffer) nil args))
144 af5ef7cd 2020-11-29 op
145 23a0b465 2020-11-30 op (defun vc-got--add (files)
146 23a0b465 2020-11-30 op "Add FILES to got, passing `vc-register-switches' to the command invocation."
147 23a0b465 2020-11-30 op (with-temp-buffer
148 23a0b465 2020-11-30 op (apply #'vc-got--call "add" (append vc-register-switches files))))
149 23a0b465 2020-11-30 op
150 9ad1eb5d 2020-12-07 op (defun vc-got--log (&optional path limit start-commit stop-commit search-pattern)
151 23a0b465 2020-11-30 op "Execute the log command in the worktree of PATH.
152 518ede14 2020-12-05 op The output in the current buffer.
153 af5ef7cd 2020-11-29 op
154 23a0b465 2020-11-30 op LIMIT limits the maximum number of commit returned.
155 23a0b465 2020-11-30 op
156 518ede14 2020-12-05 op START-COMMIT: start traversing history at the specified commit.
157 9ad1eb5d 2020-12-07 op STOP-COMMIT: stop traversing history at the specified commit.
158 518ede14 2020-12-05 op SEARCH-PATTERN: limit to log messages matched by the regexp given.
159 518ede14 2020-12-05 op
160 23a0b465 2020-11-30 op Return nil if the command failed or if PATH isn't included in any
161 23a0b465 2020-11-30 op worktree."
162 518ede14 2020-12-05 op (vc-got-with-worktree (or path default-directory)
163 518ede14 2020-12-05 op (zerop
164 518ede14 2020-12-05 op (apply #'vc-got--call
165 518ede14 2020-12-05 op (cl-remove-if #'null
166 518ede14 2020-12-05 op (flatten-list
167 518ede14 2020-12-05 op (list "log"
168 518ede14 2020-12-05 op (when limit (list "-l" (format "%s" limit)))
169 518ede14 2020-12-05 op (when start-commit (list "-c" start-commit))
170 9ad1eb5d 2020-12-07 op (when stop-commit (list "-x" stop-commit))
171 518ede14 2020-12-05 op (when search-pattern (list "-s" search-pattern))
172 518ede14 2020-12-05 op path)))))))
173 af5ef7cd 2020-11-29 op
174 af5ef7cd 2020-11-29 op (defun vc-got--status (dir-or-file &rest files)
175 af5ef7cd 2020-11-29 op "Return the output of ``got status''.
176 af5ef7cd 2020-11-29 op
177 af5ef7cd 2020-11-29 op DIR-OR-FILE can be either a directory or a file. If FILES is
178 af5ef7cd 2020-11-29 op given, return the status of those files, otherwise the status of
179 af5ef7cd 2020-11-29 op DIR-OR-FILE."
180 af5ef7cd 2020-11-29 op (vc-got-with-worktree dir-or-file
181 af5ef7cd 2020-11-29 op (with-temp-buffer
182 af5ef7cd 2020-11-29 op (if files
183 af5ef7cd 2020-11-29 op (apply #'vc-got--call "status" files)
184 af5ef7cd 2020-11-29 op (vc-got--call "status" dir-or-file))
185 af5ef7cd 2020-11-29 op (buffer-string))))
186 af5ef7cd 2020-11-29 op
187 af5ef7cd 2020-11-29 op (defun vc-got--parse-status-flag (flag)
188 af5ef7cd 2020-11-29 op "Parse FLAG, see `vc-state'."
189 af5ef7cd 2020-11-29 op ;; got outputs nothing if the file is up-to-date
190 af5ef7cd 2020-11-29 op (if (string-empty-p flag)
191 af5ef7cd 2020-11-29 op 'up-to-date
192 af5ef7cd 2020-11-29 op ;; trying to follow the order of the manpage
193 af5ef7cd 2020-11-29 op (cl-case (aref flag 0)
194 af5ef7cd 2020-11-29 op (?M 'edited)
195 af5ef7cd 2020-11-29 op (?A 'added)
196 af5ef7cd 2020-11-29 op (?D 'removed)
197 af5ef7cd 2020-11-29 op (?C 'conflict)
198 af5ef7cd 2020-11-29 op (?! 'missing)
199 af5ef7cd 2020-11-29 op (?~ 'edited) ;XXX: what does it means for a file to be ``obstructed''?
200 af5ef7cd 2020-11-29 op (?? 'unregistered)
201 af5ef7cd 2020-11-29 op (?m 'edited) ;modified file modes
202 af5ef7cd 2020-11-29 op (?N nil))))
203 af5ef7cd 2020-11-29 op
204 af5ef7cd 2020-11-29 op (defun vc-got--parse-status (output)
205 af5ef7cd 2020-11-29 op "Parse the OUTPUT of got status and return an alist of (FILE . STATUS)."
206 af5ef7cd 2020-11-29 op ;; XXX: the output of got is line-oriented and will break if
207 af5ef7cd 2020-11-29 op ;; filenames contains spaces or newlines.
208 af5ef7cd 2020-11-29 op (cl-loop for line in (split-string output "\n" t)
209 af5ef7cd 2020-11-29 op collect (cl-destructuring-bind (status file) (split-string line " " t " ")
210 af5ef7cd 2020-11-29 op `(,file . ,(vc-got--parse-status-flag status)))))
211 af5ef7cd 2020-11-29 op
212 23a0b465 2020-11-30 op (defun vc-got--tree-parse ()
213 23a0b465 2020-11-30 op "Parse into an alist the output of got tree -i in the current buffer."
214 23a0b465 2020-11-30 op (goto-char (point-min))
215 23a0b465 2020-11-30 op (cl-loop
216 23a0b465 2020-11-30 op until (= (point) (point-max))
217 23a0b465 2020-11-30 op collect (let* ((obj-start (point))
218 23a0b465 2020-11-30 op (_ (forward-word))
219 23a0b465 2020-11-30 op (obj (buffer-substring obj-start (point)))
220 23a0b465 2020-11-30 op (_ (forward-char)) ;skip the space
221 23a0b465 2020-11-30 op (filename-start (point))
222 23a0b465 2020-11-30 op (_ (move-end-of-line nil))
223 23a0b465 2020-11-30 op (filename (buffer-substring filename-start (point))))
224 23a0b465 2020-11-30 op ;; goto the start of the next line
225 23a0b465 2020-11-30 op (forward-line)
226 23a0b465 2020-11-30 op (move-beginning-of-line nil)
227 23a0b465 2020-11-30 op `(,filename . ,obj))))
228 23a0b465 2020-11-30 op
229 23a0b465 2020-11-30 op (defun vc-got--tree (commit path)
230 23a0b465 2020-11-30 op (vc-got-with-worktree path
231 23a0b465 2020-11-30 op (with-temp-buffer
232 23a0b465 2020-11-30 op (vc-got--call "tree" "-c" commit "-i" path)
233 23a0b465 2020-11-30 op (vc-got--tree-parse))))
234 23a0b465 2020-11-30 op
235 23a0b465 2020-11-30 op (defun vc-got--cat (commit obj-id)
236 23a0b465 2020-11-30 op "Execute got cat -c COMMIT OBJ-ID in the current buffer."
237 23a0b465 2020-11-30 op (vc-got--call "cat" "-c" commit obj-id))
238 eb85ad27 2020-12-05 op
239 eb85ad27 2020-12-05 op (defun vc-got--revert (&rest files)
240 eb85ad27 2020-12-05 op "Execute got revert FILES..."
241 eb85ad27 2020-12-05 op (vc-got-with-worktree (car files)
242 eb85ad27 2020-12-05 op (with-temp-buffer
243 eb85ad27 2020-12-05 op (apply #'vc-got--call "revert" files))))
244 eb85ad27 2020-12-05 op
245 eb85ad27 2020-12-05 op (defun vc-got--list-branches ()
246 eb85ad27 2020-12-05 op "Return an alist of (branch . commit)."
247 eb85ad27 2020-12-05 op (with-temp-buffer
248 eb85ad27 2020-12-05 op (when (zerop (vc-got--call "branch" "-l"))
249 eb85ad27 2020-12-05 op (goto-char (point-min))
250 eb85ad27 2020-12-05 op (cl-loop
251 eb85ad27 2020-12-05 op until (= (point) (point-max))
252 eb85ad27 2020-12-05 op ;; parse the `* $branchname: $commit', from the end
253 eb85ad27 2020-12-05 op collect (let* ((_ (move-end-of-line nil))
254 eb85ad27 2020-12-05 op (end-commit (point))
255 eb85ad27 2020-12-05 op (_ (backward-word))
256 eb85ad27 2020-12-05 op (start-commit (point))
257 eb85ad27 2020-12-05 op (_ (backward-char 2))
258 eb85ad27 2020-12-05 op (end-branchname (point))
259 eb85ad27 2020-12-05 op (_ (move-beginning-of-line nil))
260 eb85ad27 2020-12-05 op (_ (forward-char 2))
261 eb85ad27 2020-12-05 op (start-branchname (point))
262 eb85ad27 2020-12-05 op (branchname (buffer-substring start-branchname end-branchname))
263 eb85ad27 2020-12-05 op (commit (buffer-substring start-commit end-commit)))
264 eb85ad27 2020-12-05 op (forward-line)
265 eb85ad27 2020-12-05 op (move-beginning-of-line nil)
266 eb85ad27 2020-12-05 op `(,branchname . ,commit))))))
267 eb85ad27 2020-12-05 op
268 694534b4 2020-12-05 op (defun vc-got--current-branch ()
269 694534b4 2020-12-05 op "Return the current branch."
270 694534b4 2020-12-05 op (with-temp-buffer
271 694534b4 2020-12-05 op (when (zerop (vc-got--call "branch"))
272 694534b4 2020-12-05 op (string-trim (buffer-string) "" "\n"))))
273 eb85ad27 2020-12-05 op
274 eb85ad27 2020-12-05 op (defun vc-got--integrate (branch)
275 eb85ad27 2020-12-05 op "Integrate BRANCH into the current one."
276 eb85ad27 2020-12-05 op (with-temp-buffer
277 eb85ad27 2020-12-05 op (vc-got--call "integrate" branch)))
278 23a0b465 2020-11-30 op
279 eb85ad27 2020-12-05 op (defun vc-got--diff (&rest args)
280 eb85ad27 2020-12-05 op "Call got diff with ARGS. The result will be stored in the current buffer."
281 345290bf 2020-12-05 op (apply #'vc-got--call "diff"
282 12ca62f2 2020-12-26 op (append (vc-switches 'got 'diff)
283 12ca62f2 2020-12-26 op (mapcar #'file-relative-name args))))
284 eb85ad27 2020-12-05 op
285 af5ef7cd 2020-11-29 op
286 af5ef7cd 2020-11-29 op ;; Backend properties
287 af5ef7cd 2020-11-29 op
288 af5ef7cd 2020-11-29 op (defun vc-got-revision-granularity ()
289 af5ef7cd 2020-11-29 op "Got has REPOSITORY granularity."
290 af5ef7cd 2020-11-29 op 'repository)
291 af5ef7cd 2020-11-29 op
292 af5ef7cd 2020-11-29 op ;; XXX: what this should do? The description is not entirely clear
293 af5ef7cd 2020-11-29 op (defun vc-got-update-on-retrieve-tag ()
294 af5ef7cd 2020-11-29 op nil)
295 af5ef7cd 2020-11-29 op
296 af5ef7cd 2020-11-29 op
297 af5ef7cd 2020-11-29 op ;; State-querying functions
298 af5ef7cd 2020-11-29 op
299 af5ef7cd 2020-11-29 op ;;;###autoload (defun vc-got-registered (file)
300 af5ef7cd 2020-11-29 op ;;;###autoload "Return non-nil if FILE is registered with got."
301 af5ef7cd 2020-11-29 op ;;;###autoload (when (vc-find-root file ".got")
302 af5ef7cd 2020-11-29 op ;;;###autoload (load "vc-got" nil t)
303 af5ef7cd 2020-11-29 op ;;;###autoload (vc-got-registered file)))
304 af5ef7cd 2020-11-29 op
305 af5ef7cd 2020-11-29 op (defun vc-got-registered (file)
306 af5ef7cd 2020-11-29 op "Return non-nil if FILE is registered with got."
307 af5ef7cd 2020-11-29 op (if (file-directory-p file)
308 af5ef7cd 2020-11-29 op nil ;got doesn't track directories
309 4093d2f9 2020-12-04 op (when (vc-find-root file ".got")
310 4093d2f9 2020-12-04 op (let ((status (vc-got--status file)))
311 4093d2f9 2020-12-04 op (not (or (string-prefix-p "?" status)
312 4093d2f9 2020-12-04 op (string-prefix-p "N" status)))))))
313 af5ef7cd 2020-11-29 op
314 af5ef7cd 2020-11-29 op ;; (vc-got-registered "/usr/ports/mystuff/net/td")
315 af5ef7cd 2020-11-29 op ;; (vc-got-registered "/usr/ports/mystuff/net/td/Makefile")
316 af5ef7cd 2020-11-29 op ;; (vc-got-registered "/usr/ports/mystuff/tmp")
317 af5ef7cd 2020-11-29 op ;; (vc-got-registered "/usr/ports/mystuff/no-existant")
318 af5ef7cd 2020-11-29 op
319 af5ef7cd 2020-11-29 op (defun vc-got-state (file)
320 af5ef7cd 2020-11-29 op "Return the current version control state of FILE. See `vc-state'."
321 af5ef7cd 2020-11-29 op (unless (file-directory-p file)
322 af5ef7cd 2020-11-29 op (vc-got--parse-status-flag (vc-got--status file))))
323 af5ef7cd 2020-11-29 op
324 af5ef7cd 2020-11-29 op ;; (vc-got-state "/usr/ports/mystuff/net/td")
325 af5ef7cd 2020-11-29 op ;; (vc-got-state "/usr/ports/mystuff/net/td/Makefile")
326 af5ef7cd 2020-11-29 op ;; (vc-got-state "/usr/ports/mystuff/tmp")
327 af5ef7cd 2020-11-29 op ;; (vc-got-state "/usr/ports/mystuff/non-existant")
328 af5ef7cd 2020-11-29 op
329 af5ef7cd 2020-11-29 op (defun vc-got-dir-status-files (dir files update-function)
330 af5ef7cd 2020-11-29 op (let* ((files (seq-filter (lambda (file)
331 af5ef7cd 2020-11-29 op (and (not (string= file ".."))
332 af5ef7cd 2020-11-29 op (not (string= file "."))
333 af5ef7cd 2020-11-29 op (not (string= file ".got"))))
334 af5ef7cd 2020-11-29 op (or files
335 af5ef7cd 2020-11-29 op (directory-files dir))))
336 af5ef7cd 2020-11-29 op (statuses (vc-got--parse-status
337 af5ef7cd 2020-11-29 op (apply #'vc-got--status dir files)))
338 af5ef7cd 2020-11-29 op (default-directory dir))
339 af5ef7cd 2020-11-29 op (cl-loop
340 af5ef7cd 2020-11-29 op with result = nil
341 af5ef7cd 2020-11-29 op for file in files
342 af5ef7cd 2020-11-29 op do (setq result
343 af5ef7cd 2020-11-29 op (cons
344 af5ef7cd 2020-11-29 op (if (file-directory-p file)
345 af5ef7cd 2020-11-29 op (list file 'unregistered nil)
346 af5ef7cd 2020-11-29 op (if-let (status (cdr (assoc file statuses #'string=)))
347 af5ef7cd 2020-11-29 op (list file status nil)
348 af5ef7cd 2020-11-29 op (list file 'up-to-date nil)))
349 af5ef7cd 2020-11-29 op result))
350 af5ef7cd 2020-11-29 op finally (funcall update-function result nil))))
351 af5ef7cd 2020-11-29 op
352 af5ef7cd 2020-11-29 op ;; (let ((dir "/usr/ports/mystuff"))
353 af5ef7cd 2020-11-29 op ;; (vc-got-dir-status-files dir nil (lambda (res _t)
354 af5ef7cd 2020-11-29 op ;; (message "got %s" res))))
355 af5ef7cd 2020-11-29 op
356 a8466f02 2020-12-07 op (defun vc-got-dir-extra-headers (_dir)
357 a8466f02 2020-12-07 op (concat
358 a8466f02 2020-12-07 op (propertize "Branch : " 'face 'font-lock-type-face)
359 a8466f02 2020-12-07 op (vc-got--current-branch)))
360 a8466f02 2020-12-07 op
361 af5ef7cd 2020-11-29 op (defun vc-got-working-revision (file)
362 c0c9a339 2020-12-04 op "Return the id of the last commit that touched the FILE or \"0\" for a new (but added) file."
363 af5ef7cd 2020-11-29 op (or
364 af5ef7cd 2020-11-29 op (with-temp-buffer
365 518ede14 2020-12-05 op (when (vc-got--log file 1)
366 af5ef7cd 2020-11-29 op (let (start)
367 af5ef7cd 2020-11-29 op (goto-char (point-min))
368 af5ef7cd 2020-11-29 op (forward-line 1) ;skip the ----- line
369 af5ef7cd 2020-11-29 op (forward-word) ;skip "commit"
370 af5ef7cd 2020-11-29 op (forward-char) ;skip the space
371 af5ef7cd 2020-11-29 op (setq start (point)) ;store start of the SHA
372 af5ef7cd 2020-11-29 op (forward-word) ;goto SHA end
373 af5ef7cd 2020-11-29 op (buffer-substring start (point)))))
374 af5ef7cd 2020-11-29 op ;; special case: if this file is added but has no previous commits
375 af5ef7cd 2020-11-29 op ;; touching it, got log will fail (as expected), but we have to
376 af5ef7cd 2020-11-29 op ;; return "0".
377 af5ef7cd 2020-11-29 op (when (eq (vc-got-state file) 'added)
378 af5ef7cd 2020-11-29 op "0")))
379 af5ef7cd 2020-11-29 op
380 af5ef7cd 2020-11-29 op ;; (vc-got-working-revision "/usr/ports/mystuff/non-existant")
381 af5ef7cd 2020-11-29 op ;; (vc-got-working-revision "/usr/ports/mystuff/CVS")
382 af5ef7cd 2020-11-29 op ;; (vc-got-working-revision "/usr/ports/mystuff/tmp")
383 af5ef7cd 2020-11-29 op ;; (vc-got-working-revision "/usr/ports/mystuff/net/td/Makefile")
384 af5ef7cd 2020-11-29 op
385 af5ef7cd 2020-11-29 op (defun vc-got-checkout-model (_files)
386 af5ef7cd 2020-11-29 op 'implicit)
387 af5ef7cd 2020-11-29 op
388 694534b4 2020-12-05 op (defun vc-got-mode-line-string (file)
389 694534b4 2020-12-05 op "Return the VC mode line string for FILE."
390 694534b4 2020-12-05 op (vc-got-with-worktree file
391 694534b4 2020-12-05 op (let ((def (vc-default-mode-line-string 'Got file)))
392 694534b4 2020-12-05 op (concat (substring def 0 4) (vc-got--current-branch)))))
393 694534b4 2020-12-05 op
394 23a0b465 2020-11-30 op
395 23a0b465 2020-11-30 op ;; state-changing functions
396 23a0b465 2020-11-30 op
397 23a0b465 2020-11-30 op (defun vc-got-create-repo (_backend)
398 23a0b465 2020-11-30 op (error "vc got: create-repo not implemented"))
399 23a0b465 2020-11-30 op
400 23a0b465 2020-11-30 op (defun vc-got-register (files &optional _comment)
401 23a0b465 2020-11-30 op "Register FILES, passing `vc-register-switches' to the backend command."
402 23a0b465 2020-11-30 op (vc-got--add files))
403 23a0b465 2020-11-30 op
404 9e805da8 2020-11-30 op (defalias 'vc-got-responsible-p #'vc-got-root)
405 23a0b465 2020-11-30 op
406 23a0b465 2020-11-30 op (defun vc-got-checkin (files comment &optional _rev)
407 23a0b465 2020-11-30 op "Commit FILES with COMMENT as commit message."
408 23a0b465 2020-11-30 op (with-temp-buffer
409 30dcedec 2020-12-05 op (apply #'vc-got--call "commit" "-m"
410 30dcedec 2020-12-05 op ;; emacs add ``Summary:'' at the start of the commit
411 30dcedec 2020-12-05 op ;; message. vc-git doesn't seem to treat this specially.
412 30dcedec 2020-12-05 op ;; Since it's annoying, remove it.
413 30dcedec 2020-12-05 op (string-remove-prefix "Summary: " comment)
414 30dcedec 2020-12-05 op files)))
415 23a0b465 2020-11-30 op
416 23a0b465 2020-11-30 op (defun vc-got-find-revision (file rev buffer)
417 c0c9a339 2020-12-04 op "Fill BUFFER with the content of FILE in the given revision REV."
418 23a0b465 2020-11-30 op (when-let (obj-id (assoc file (vc-got--tree rev file) #'string=))
419 23a0b465 2020-11-30 op (with-current-buffer buffer
420 23a0b465 2020-11-30 op (vc-got-with-worktree file
421 23a0b465 2020-11-30 op (vc-got--cat rev obj-id)))))
422 23a0b465 2020-11-30 op
423 55091167 2020-12-05 op (defun vc-got-find-ignore-file (file)
424 55091167 2020-12-05 op "Return the gitignore file that controls FILE."
425 55091167 2020-12-05 op (expand-file-name ".gitignore"
426 55091167 2020-12-05 op (vc-got-root file)))
427 55091167 2020-12-05 op
428 eb85ad27 2020-12-05 op (defun vc-got-checkout (_file &optional _rev)
429 eb85ad27 2020-12-05 op "Checkout revision REV of FILE. If REV is t, checkout from the head."
430 eb85ad27 2020-12-05 op (error "vc got: checkout not implemented"))
431 eb85ad27 2020-12-05 op
432 eb85ad27 2020-12-05 op (defun vc-got-revert (file &optional _content-done)
433 eb85ad27 2020-12-05 op "Revert FILE back to working revision."
434 eb85ad27 2020-12-05 op (vc-got--revert file))
435 eb85ad27 2020-12-05 op
436 eb85ad27 2020-12-05 op (defun vc-got-merge-branch ()
437 eb85ad27 2020-12-05 op "Prompt for a branch and integrate it into the current one."
438 eb85ad27 2020-12-05 op ;; XXX: be smart and try to "got rebase" if "got integrate" fails?
439 eb85ad27 2020-12-05 op (let* ((branches (cl-loop for (branch . commit) in (vc-got--list-branches)
440 eb85ad27 2020-12-05 op collect branch))
441 eb85ad27 2020-12-05 op (branch (completing-read "Merge from branch: " branches)))
442 eb85ad27 2020-12-05 op (when branch
443 eb85ad27 2020-12-05 op (vc-got--integrate branch))))
444 686eac9a 2020-12-07 op
445 686eac9a 2020-12-07 op (defun vc-got--push-pull (cmd op prompt root)
446 686eac9a 2020-12-07 op "Execute CMD OP, or prompt the user if PROMPT is non-nil.
447 686eac9a 2020-12-07 op ROOT is the worktree root."
448 686eac9a 2020-12-07 op (let ((buffer (format "*vc-got : %s*" (expand-file-name root))))
449 686eac9a 2020-12-07 op (when-let (cmd (if prompt
450 686eac9a 2020-12-07 op (split-string
451 686eac9a 2020-12-07 op (read-shell-command (format "%s %s command: " cmd op)
452 686eac9a 2020-12-07 op (format "%s %s" cmd op))
453 686eac9a 2020-12-07 op " " t)
454 686eac9a 2020-12-07 op (list cmd op)))
455 686eac9a 2020-12-07 op (apply #'vc-do-command buffer 0 (car cmd) nil (cdr cmd)))))
456 eb85ad27 2020-12-05 op
457 eb85ad27 2020-12-05 op (defun vc-got-pull (prompt)
458 eb85ad27 2020-12-05 op "Execute got pull, prompting the user for the full command if PROMPT is not nil."
459 686eac9a 2020-12-07 op (vc-got--push-pull vc-got-cmd "fetch" prompt (vc-got-root default-directory)))
460 686eac9a 2020-12-07 op
461 686eac9a 2020-12-07 op (defun vc-got-push (prompt)
462 686eac9a 2020-12-07 op "Run git push (not got!) in the repository dir.
463 686eac9a 2020-12-07 op If PROMPT is non-nil, prompt for the git command to run."
464 eb85ad27 2020-12-05 op (let* ((root (vc-got-root default-directory))
465 686eac9a 2020-12-07 op (default-directory (vc-got--repo-root)))
466 686eac9a 2020-12-07 op (vc-got--push-pull "git" "push" prompt root)))
467 eb85ad27 2020-12-05 op
468 eb85ad27 2020-12-05 op (defun vc-got-print-log (files buffer &optional _shortlog start-revision limit)
469 eb85ad27 2020-12-05 op "Insert the revision log for FILES into BUFFER.
470 eb85ad27 2020-12-05 op
471 eb85ad27 2020-12-05 op LIMIT limits the number of commits, optionally starting at START-REVISION."
472 eb85ad27 2020-12-05 op (with-current-buffer buffer
473 eb85ad27 2020-12-05 op ;; the *vc-diff* may be read only
474 4571b1fd 2020-12-05 op (let ((inhibit-read-only t))
475 eb85ad27 2020-12-05 op (cl-loop for file in files
476 4571b1fd 2020-12-05 op do (vc-got--log (file-relative-name file) limit start-revision)))))
477 eb85ad27 2020-12-05 op
478 9ad1eb5d 2020-12-07 op ;; XXX: this includes also the latest commit in REMOTE-LOCATION.
479 9ad1eb5d 2020-12-07 op (defun vc-got-log-outgoing (buffer remote-location)
480 9ad1eb5d 2020-12-07 op "Fill BUFFER with the diff between the local worktree branch and REMOTE-LOCATION."
481 9ad1eb5d 2020-12-07 op (vc-setup-buffer buffer)
482 9ad1eb5d 2020-12-07 op (let ((rl (if (or (not remote-location) (string-empty-p remote-location))
483 9ad1eb5d 2020-12-07 op (concat "origin/" (vc-got--current-branch))
484 9ad1eb5d 2020-12-07 op remote-location))
485 9ad1eb5d 2020-12-07 op (inhibit-read-only t))
486 9ad1eb5d 2020-12-07 op (with-current-buffer buffer
487 9ad1eb5d 2020-12-07 op (vc-got--log nil nil nil rl))))
488 6eda2f1f 2020-12-26 op
489 6eda2f1f 2020-12-26 op (defun vc-got-incoming (buffer remote-location)
490 6eda2f1f 2020-12-26 op "Fill BUFFER with the diff between the REMOTE-LOCATION and the local worktree branch."
491 6eda2f1f 2020-12-26 op (let ((rl (if (or (not remote-location) (string-empty-p remote-location))
492 6eda2f1f 2020-12-26 op (concat "origin/" (vc-got--current-branch))
493 6eda2f1f 2020-12-26 op remote-location))
494 6eda2f1f 2020-12-26 op (inhibit-read-only t))
495 6eda2f1f 2020-12-26 op (with-current-buffer buffer
496 6eda2f1f 2020-12-26 op (vc-got--log nil nil (vc-got--current-branch) rl))))
497 9ad1eb5d 2020-12-07 op
498 eb85ad27 2020-12-05 op (defun vc-got-log-search (buffer pattern)
499 eb85ad27 2020-12-05 op "Search commits for PATTERN and write the results found in BUFFER."
500 eb85ad27 2020-12-05 op (with-current-buffer buffer
501 eb85ad27 2020-12-05 op (let ((inhibit-read-only t))
502 9ad1eb5d 2020-12-07 op (vc-got--log nil nil nil nil pattern))))
503 eb85ad27 2020-12-05 op
504 eb85ad27 2020-12-05 op ;; TODO: async
505 f18d3e11 2020-12-05 op ;; TODO: return 0 or 1
506 eb85ad27 2020-12-05 op (defun vc-got-diff (files &optional rev1 rev2 buffer _async)
507 eb85ad27 2020-12-05 op "Insert into BUFFER (or *vc-diff*) the diff for FILES from REV1 to REV2."
508 eb85ad27 2020-12-05 op (message "vc-got: debug: files is %s" files)
509 f457868b 2020-12-07 op (let* ((buffer (get-buffer-create (or buffer "*vc-diff*")))
510 eb85ad27 2020-12-05 op (inhibit-read-only t))
511 eb85ad27 2020-12-05 op (with-current-buffer buffer
512 ba123905 2020-12-08 op (vc-got-stage-mode +1)
513 ba123905 2020-12-08 op ;; TODO: this shouldn't be done in an unconditioned fashion. If
514 ba123905 2020-12-08 op ;; we're diffing two revision, we can't stage hunks; we can
515 ba123905 2020-12-08 op ;; stage only when diffing the local modifications.
516 ba123905 2020-12-08 op (setq vc-got-stage-fileset files)
517 eb85ad27 2020-12-05 op (vc-got-with-worktree (car files)
518 eb85ad27 2020-12-05 op (cond ((and (null rev1)
519 eb85ad27 2020-12-05 op (null rev2))
520 345290bf 2020-12-05 op (apply #'vc-got--diff files))
521 eb85ad27 2020-12-05 op (t (error "Not implemented")))))))
522 eb85ad27 2020-12-05 op
523 af5ef7cd 2020-11-29 op (provide 'vc-got)
524 af5ef7cd 2020-11-29 op ;;; vc-got.el ends here