changelog shortlog graph tags branches changeset files revisions annotate raw help

Mercurial > core / lisp/lib/vc/proto.lisp

changeset 698: 96958d3eb5b0
parent: 35a579313b80
author: Richard Westhaver <ellis@rwest.io>
date: Fri, 04 Oct 2024 22:04:59 -0400
permissions: -rw-r--r--
description: fixes
1 ;;; lib/vc/proto.lisp --- VC Protocol
2 
3 ;;
4 
5 ;;; Code:
6 (in-package :vc/proto)
7 
8 ;;; Conditions
9 (define-condition vc-error (std-error) ())
10 
11 ;;; Utils
12 (defun namestring-or (obj)
13  (if (pathnamep obj)
14  (namestring obj)
15  obj))
16 
17 (defun rel-pathname (path)
18  (pathname (string-left-trim '(#\/) path)))
19 
20 (defun glob-path-match (glob)
21  (lambda (p start end)
22  (member (subseq p start end) (directory (rel-pathname glob)) :test 'equal)))
23 
24 ;;; Functions
25 (defgeneric vc-init (self)
26  (:documentation "Initialize a vc-repo - calls either 'git init' or 'hg init'"))
27 
28 (defgeneric vc-run (self cmd &rest args)
29  (:documentation "Run a vc CMD with ARGS."))
30 
31 (defgeneric vc-id (self)
32  (:documentation "Get the ID of a vc object."))
33 
34 (defgeneric (setf vc-id) (self id)
35  (:documentation "Set the ID of a vc object."))
36 
37 (defgeneric vc-clone (self remote &key &allow-other-keys)
38  (:documentation "Clone repo REMOTE into spec SELF."))
39 
40 (defgeneric vc-push (self &optional remote)
41  (:documentation "Push repo SELF to REMOTE."))
42 
43 (defgeneric vc-pull (self &optional remote)
44  (:documentation "Pull repo REMOTE into spec SELF."))
45 
46 (defgeneric vc-update (self &optional branch)
47  (:documentation "Update repo SELF with optional BRANCH."))
48 
49 (defgeneric vc-commit (self msg &key &allow-other-keys)
50  (:documentation "Commit repo object SELF, supplied with message MSG."))
51 
52 (defgeneric vc-add (self &rest files)
53  (:documentation "Add FILES to repo SELF."))
54 
55 (defgeneric vc-remove (self &rest files)
56  (:documentation "Remove FILES from repo SELF."))
57 
58 (defgeneric vc-addremove (self &rest files)
59  (:documentation "Add any untracked files in the current directory and delete tracked files that
60 are missing."))
61 
62 (defgeneric vc-branch (self)
63  (:documentation "Return the name of the current branch."))
64 
65 (defgeneric vc-status (self &key &allow-other-keys))
66 
67 (defgeneric vc-bundle (self output &key &allow-other-keys))
68 (defgeneric vc-unbundle (self input &key &allow-other-keys))
69 
70 ;;; Accessors
71 (defgeneric vc-name (self))
72 (defgeneric vc-path (self))
73 (defgeneric vc-head (self))
74 (defgeneric vc-tags (self))
75 (defgeneric vc-revs (self))
76 (defgeneric vc-branches (self))
77 (defgeneric vc-remotes (self))
78 (defgeneric vc-config (self))
79 
80 ;; IDEA 2023-12-29: :ediff t
81 (defgeneric vc-diff (a b &key &allow-other-keys))
82 
83 ;;; Objects
84 
85 ;;;; Config
86 
87 ;; usually parsed from .gitconfig or .hgrc
88 (defclass vc-config (cfg) ())
89 
90 ;;;; Ignorefile
91 
92 ;; Basically we treat HG and GIT ignore files the same - just lines of string
93 ;; patterns. HG uses regexp and GIT is globs - an IGNOREFILE has a line parser
94 ;; slot for selecting the appropriate function.
95 
96 (defun map-lines (fn path)
97  "Call FN on each line of file PATH and collect the result."
98  (with-open-file (file path)
99  (loop for line = (read-line file nil)
100  while line
101  unless (or (= (length line) 0) (char= (aref line 0) #\#))
102  collect (funcall fn line))))
103 
104 (defstruct vc-ignore path patterns)
105 
106 (defgeneric vc-path-ignored-p (obj path)
107  (:documentation "Check PATH against the patterns in OBJ. If there is a match, return non-nil.")
108  (:method ((obj vc-ignore) (path t))
109  (let ((len (length path)))
110  (loop for pat in (vc-ignore-patterns obj)
111  when (funcall pat path 0 len)
112  return (values path pat)))))
113 
114 (defstruct vc-branch name rev)
115 
116 (defstruct vc-commit id message)
117 
118 (defstruct vc-tag name id)
119 
120 (defstruct vc-remote name url)
121 
122 (defstruct vc-rev num id)
123 
124 (defclass vc-repo ()
125  ((path :initform nil :type (or null string pathname) :accessor vc-path
126  :initarg :path
127  :documentation "AKA working-directory or working-copy")
128  (head :initform nil :initarg :head :type (or null vc-rev) :accessor vc-head)
129  (branches :initform (make-array 0 :element-type 'vc-branch :fill-pointer 0)
130  :type (vector vc-branch) :accessor vc-branches)
131  (tags :initform (make-array 0 :element-type 'vc-tag :fill-pointer 0) :type (vector vc-tag) :accessor vc-tags)
132  (revisions :initform (make-array 0 :element-type 'vc-rev :fill-pointer 0)
133  :type (vector vc-rev) :accessor vc-revs)
134  (remotes :initform (make-array 0 :element-type 'vc-remote :fill-pointer 0)
135  :type (vector vc-remote) :accessor vc-remotes)
136  (config :initform nil :type (or null vc-config) :accessor vc-config))
137  (:documentation "generic Repository object backed by one of VC-DESIGNATOR."))
138 
139 (defmethod vc-init ((self (eql t)))
140  (make-instance 'vc-repo))
141 
142 (defmethod vc-name ((self vc-repo))
143  (car (last (pathname-directory (vc-path self)))))