vc-src.el 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314
  1. ;;; vc-src.el --- support for SRC version-control -*- lexical-binding:t -*-
  2. ;; Copyright (C) 1992-2015 Free Software Foundation, Inc.
  3. ;; Author: FSF (see vc.el for full credits)
  4. ;; Maintainer: Eric S. Raymond <esr@thyrsus.com>
  5. ;; Package: vc
  6. ;; This file is part of GNU Emacs.
  7. ;; GNU Emacs is free software: you can redistribute it and/or modify
  8. ;; it under the terms of the GNU General Public License as published by
  9. ;; the Free Software Foundation, either version 3 of the License, or
  10. ;; (at your option) any later version.
  11. ;; GNU Emacs is distributed in the hope that it will be useful,
  12. ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. ;; GNU General Public License for more details.
  15. ;; You should have received a copy of the GNU General Public License
  16. ;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
  17. ;;; Commentary:
  18. ;; See vc.el. SRC requires an underlying RCS version of 4.0 or greater.
  19. ;; FUNCTION NAME STATUS
  20. ;; BACKEND PROPERTIES
  21. ;; * revision-granularity OK
  22. ;; STATE-QUERYING FUNCTIONS
  23. ;; * registered (file) OK
  24. ;; * state (file) OK
  25. ;; - dir-status-files (dir files uf) OK
  26. ;; - dir-extra-headers (dir) NOT NEEDED
  27. ;; - dir-printer (fileinfo) ??
  28. ;; * working-revision (file) OK
  29. ;; * checkout-model (files) OK
  30. ;; - mode-line-string (file) NOT NEEDED
  31. ;; STATE-CHANGING FUNCTIONS
  32. ;; * register (files &optional rev comment) OK
  33. ;; * create-repo () OK
  34. ;; * responsible-p (file) OK
  35. ;; - receive-file (file rev) NOT NEEDED
  36. ;; - unregister (file) NOT NEEDED
  37. ;; * checkin (files comment) OK
  38. ;; * find-revision (file rev buffer) OK
  39. ;; * checkout (file &optional rev) OK
  40. ;; * revert (file &optional contents-done) OK
  41. ;; - merge (file rev1 rev2) NOT NEEDED
  42. ;; - merge-news (file) NOT NEEDED
  43. ;; - steal-lock (file &optional revision) NOT NEEDED
  44. ;; HISTORY FUNCTIONS
  45. ;; * print-log (files buffer &optional shortlog start-revision limit) OK
  46. ;; - log-view-mode () ??
  47. ;; - show-log-entry (revision) NOT NEEDED
  48. ;; - comment-history (file) NOT NEEDED
  49. ;; - update-changelog (files) NOT NEEDED
  50. ;; * diff (files &optional rev1 rev2 buffer) OK
  51. ;; - revision-completion-table (files) ??
  52. ;; - annotate-command (file buf &optional rev) ??
  53. ;; - annotate-time () ??
  54. ;; - annotate-current-time () NOT NEEDED
  55. ;; - annotate-extract-revision-at-line () ??
  56. ;; TAG SYSTEM
  57. ;; - create-tag (dir name branchp) ??
  58. ;; - retrieve-tag (dir name update) ??
  59. ;; MISCELLANEOUS
  60. ;; - make-version-backups-p (file) ??
  61. ;; - previous-revision (file rev) ??
  62. ;; - next-revision (file rev) ??
  63. ;; - check-headers () ??
  64. ;; - delete-file (file) ??
  65. ;; * rename-file (old new) OK
  66. ;; - find-file-hook () NOT NEEDED
  67. ;;; Code:
  68. ;;;
  69. ;;; Customization options
  70. ;;;
  71. (eval-when-compile
  72. (require 'cl-lib)
  73. (require 'vc))
  74. (defgroup vc-src nil
  75. "VC SRC backend."
  76. :version "25.1"
  77. :group 'vc)
  78. (defcustom vc-src-release nil
  79. "The release number of your SRC installation, as a string.
  80. If nil, VC itself computes this value when it is first needed."
  81. :type '(choice (const :tag "Auto" nil)
  82. (string :tag "Specified")
  83. (const :tag "Unknown" unknown))
  84. :group 'vc-src)
  85. (defcustom vc-src-program "src"
  86. "Name of the SRC executable (excluding any arguments)."
  87. :type 'string
  88. :group 'vc-src)
  89. (defcustom vc-src-diff-switches nil
  90. "String or list of strings specifying switches for SRC diff under VC.
  91. If nil, use the value of `vc-diff-switches'. If t, use no switches."
  92. :type '(choice (const :tag "Unspecified" nil)
  93. (const :tag "None" t)
  94. (string :tag "Argument String")
  95. (repeat :tag "Argument List" :value ("") string))
  96. :group 'vc-src)
  97. ;; This needs to be autoloaded because vc-src-registered uses it (via
  98. ;; vc-default-registered), and vc-hooks needs to be able to check
  99. ;; for a registered backend without loading every backend.
  100. ;;;###autoload
  101. (defcustom vc-src-master-templates
  102. (purecopy '("%s.src/%s,v"))
  103. "Where to look for SRC master files.
  104. For a description of possible values, see `vc-check-master-templates'."
  105. :type '(choice (const :tag "Use standard SRC file names"
  106. '("%s.src/%s,v"))
  107. (repeat :tag "User-specified"
  108. (choice string
  109. function)))
  110. :group 'vc-src)
  111. ;;; Properties of the backend
  112. (defun vc-src-revision-granularity () 'file)
  113. (defun vc-src-checkout-model (_files) 'implicit)
  114. ;;;
  115. ;;; State-querying functions
  116. ;;;
  117. ;; The autoload cookie below places vc-src-registered directly into
  118. ;; loaddefs.el, so that vc-src.el does not need to be loaded for
  119. ;; every file that is visited.
  120. ;;;###autoload
  121. (progn
  122. (defun vc-src-registered (f) (vc-default-registered 'src f)))
  123. (defun vc-src-state (file)
  124. "SRC-specific version of `vc-state'."
  125. (let*
  126. ((status nil)
  127. (default-directory (file-name-directory file))
  128. (out
  129. (with-output-to-string
  130. (with-current-buffer
  131. standard-output
  132. (setq status
  133. ;; Ignore all errors.
  134. (condition-case nil
  135. (process-file
  136. vc-src-program nil t nil
  137. "status" "-a" (file-relative-name file))
  138. (error nil)))))))
  139. (when (eq 0 status)
  140. (when (null (string-match "does not exist or is unreadable" out))
  141. (let ((state (aref out 0)))
  142. (cond
  143. ;; FIXME: What to do about A and L codes?
  144. ((eq state ?.) 'up-to-date)
  145. ((eq state ?A) 'added)
  146. ((eq state ?M) 'edited)
  147. ((eq state ?I) 'ignored)
  148. ((eq state ?R) 'removed)
  149. ((eq state ?!) 'missing)
  150. ((eq state ??) 'unregistered)
  151. (t 'up-to-date)))))))
  152. (autoload 'vc-expand-dirs "vc")
  153. (defun vc-src-dir-status-files (dir files update-function)
  154. ;; FIXME: Use one src status -a call for this
  155. (if (not files) (setq files (vc-expand-dirs (list dir) 'RCS)))
  156. (let ((result nil))
  157. (dolist (file files)
  158. (let ((state (vc-state file))
  159. (frel (file-relative-name file)))
  160. (when (and (eq (vc-backend file) 'SRC)
  161. (not (eq state 'up-to-date)))
  162. (push (list frel state) result))))
  163. (funcall update-function result)))
  164. (defun vc-src-command (buffer file-or-list &rest flags)
  165. "A wrapper around `vc-do-command' for use in vc-src.el.
  166. This function differs from vc-do-command in that it invokes `vc-src-program'."
  167. (let (file-list)
  168. (cond ((stringp file-or-list)
  169. (setq file-list (list "--" file-or-list)))
  170. (file-or-list
  171. (setq file-list (cons "--" file-or-list))))
  172. (apply 'vc-do-command (or buffer "*vc*") 0 vc-src-program file-list flags)))
  173. (defun vc-src-working-revision (file)
  174. "SRC-specific version of `vc-working-revision'."
  175. (let ((result (ignore-errors
  176. (with-output-to-string
  177. (vc-src-command standard-output file "list" "-f{1}" "@")))))
  178. (if (zerop (length result)) "0" result)))
  179. ;;;
  180. ;;; State-changing functions
  181. ;;;
  182. (defun vc-src-create-repo ()
  183. "Create a new SRC repository."
  184. ;; SRC is totally file-oriented, so all we have to do is make the directory.
  185. (make-directory ".src"))
  186. (autoload 'vc-switches "vc")
  187. (defun vc-src-register (files &optional _comment)
  188. "Register FILES under src. COMMENT is ignored."
  189. (vc-src-command nil files "add"))
  190. (defun vc-src-responsible-p (file)
  191. "Return non-nil if SRC thinks it would be responsible for registering FILE."
  192. (file-directory-p (expand-file-name ".src"
  193. (if (file-directory-p file)
  194. file
  195. (file-name-directory file)))))
  196. (defun vc-src-checkin (files comment &optional _rev)
  197. "SRC-specific version of `vc-backend-checkin'.
  198. REV is ignored."
  199. (vc-src-command nil files "commit" "-m" comment))
  200. (defun vc-src-find-revision (file rev buffer)
  201. (let ((coding-system-for-read 'binary)
  202. (coding-system-for-write 'binary))
  203. (if rev
  204. (vc-src-command buffer file "cat" rev)
  205. (vc-src-command buffer file "cat"))))
  206. (defun vc-src-checkout (file &optional rev)
  207. "Retrieve a revision of FILE.
  208. REV is the revision to check out into WORKFILE."
  209. (if rev
  210. (vc-src-command nil file "co" rev)
  211. (vc-src-command nil file "co")))
  212. (defun vc-src-revert (file &optional _contents-done)
  213. "Revert FILE to the version it was based on. If FILE is a directory,
  214. revert all registered files beneath it."
  215. (if (file-directory-p file)
  216. (mapc 'vc-src-revert (vc-expand-dirs (list file) 'SRC))
  217. (vc-src-command nil file "co")))
  218. (defun vc-src-modify-change-comment (files rev comment)
  219. "Modify the change comments change on FILES on a specified REV. If FILE is a
  220. directory the operation is applied to all registered files beneath it."
  221. (dolist (file (vc-expand-dirs files 'SRC))
  222. (vc-src-command nil file "amend" "-m" comment rev)))
  223. ;; History functions
  224. (defcustom vc-src-log-switches nil
  225. "String or list of strings specifying switches for src log under VC."
  226. :type '(choice (const :tag "None" nil)
  227. (string :tag "Argument String")
  228. (repeat :tag "Argument List" :value ("") string))
  229. :group 'vc-src)
  230. (defun vc-src-print-log (files buffer &optional shortlog _start-revision limit)
  231. "Print commit log associated with FILES into specified BUFFER.
  232. If SHORTLOG is non-nil, use the list method.
  233. If START-REVISION is non-nil, it is the newest revision to show.
  234. If LIMIT is non-nil, show no more than this many entries."
  235. ;; FIXME: Implement the range restrictions.
  236. ;; `vc-do-command' creates the buffer, but we need it before running
  237. ;; the command.
  238. (vc-setup-buffer buffer)
  239. ;; If the buffer exists from a previous invocation it might be
  240. ;; read-only.
  241. (let ((inhibit-read-only t))
  242. (with-current-buffer
  243. buffer
  244. (apply 'vc-src-command buffer files (if shortlog "list" "log")
  245. (nconc
  246. ;;(when start-revision (list (format "%s-1" start-revision)))
  247. (when limit (list "-l" (format "%s" limit)))
  248. vc-src-log-switches)))))
  249. (defun vc-src-diff (files &optional oldvers newvers buffer _async)
  250. "Get a difference report using src between two revisions of FILES."
  251. (let* ((firstfile (car files))
  252. (working (and firstfile (vc-working-revision firstfile))))
  253. (when (and (equal oldvers working) (not newvers))
  254. (setq oldvers nil))
  255. (when (and (not oldvers) newvers)
  256. (setq oldvers working))
  257. (apply #'vc-src-command (or buffer "*vc-diff*") files "diff"
  258. (when oldvers
  259. (if newvers
  260. (list (concat oldvers "-" newvers))
  261. (list oldvers))))))
  262. ;; Miscellaneous
  263. (defun vc-src-rename-file (old new)
  264. "Rename file from OLD to NEW using `src mv'."
  265. (vc-src-command nil 0 new "mv" old))
  266. (provide 'vc-src)
  267. ;;; vc-src.el ends here