unofficial mirror of emacs-devel@gnu.org 
 help / color / mirror / code / Atom feed
* Updating *vc-dir* marks from *VC-log*
@ 2010-11-21  0:58 Bob Rogers
  2010-11-21  4:46 ` Dan Nicolaescu
  2010-11-21 18:43 ` Stefan Monnier
  0 siblings, 2 replies; 8+ messages in thread
From: Bob Rogers @ 2010-11-21  0:58 UTC (permalink / raw)
  To: emacs-devel

   Perhaps I'm slow, but I only just noticed that it is possible to work
on multiple VC commits for the same working copy in parallel, just by
renaming *VC-log* buffers.  This is cool; it perfectly suits my working
style.  I would like to write it up for the Emacs manual so that others
can find it.

   But it lacks something.  I often start a commit, then realize that
I've left out a file or two, or maybe included one that ought to be
committed separately.  When doing one commit at a time, this is a simple
matter of returning to vc-dir, updating the set, and doing "C-x v v"
again.  With multiple pending commits, what is needed is a way to return
to vc-dir and "swap in" the log buffer fileset.  The patch below adds a
new log-edit-visit-files-in-vc-dir command to do this.  I have
tentatively bound it to "C-c @" in log-edit-mode, which I hope is
sufficiently mnemonic for "mark".

   The only problem is that "C-x v v" doesn't know to which of several
log buffers it should return from *vc-dir*; it always picks *VC-log*,
creating a new one if necessary.  I could hack vc-checkin, but one would
still need to be able to specify when to go back to the relevant log
buffer, and when to create a new one.

   Comments?

					-- Bob Rogers
					   http://www.rgrjr.com/

------------------------------------------------------------------------
diff --git a/lisp/vc/log-edit.el b/lisp/vc/log-edit.el
index 27290ee..726a074 100644
--- a/lisp/vc/log-edit.el
+++ b/lisp/vc/log-edit.el
@@ -57,6 +57,7 @@
     ("\C-c\C-a" . log-edit-insert-changelog)
     ("\C-c\C-d" . log-edit-show-diff)
     ("\C-c\C-f" . log-edit-show-files)
+    ("\C-c@"    . log-edit-visit-files-in-vc-dir)
     ("\M-n"	. log-edit-next-comment)
     ("\M-p"	. log-edit-previous-comment)
     ("\M-r"	. log-edit-comment-search-backward)
@@ -533,6 +534,40 @@ If you want to abort the commit, simply delete the buffer."
 	(shrink-window-if-larger-than-buffer)
 	(selected-window)))))
 
+(defun log-edit-visit-files-in-vc-dir ()
+  "Switch to vc-dir, marking the list of files to be committed."
+  (interactive)
+  (let ((files (mapcar 'expand-file-name (log-edit-files)))
+	(buffers nil))
+    ;; Find the set of possible vc-dir buffers.
+    (let ((tail files))
+      (while tail
+	(let* ((buf-and-node (vc-dir-find-buffer-for-file (car tail)))
+	       (buffer (car buf-and-node)))
+	  (message "got %S for %S" buf-and-node (car tail))
+	  (if (and buffer
+		   (not (member buffer buffers)))
+	      (setq buffers (cons buffer buffers))))
+	(setq tail (cdr tail))))
+    (cond ((null buffers)
+	    ;; Totally failed, so offer to start vc-dir.
+	    (call-interactively 'vc-dir))
+	  ((not (null (cdr buffers)))
+	    ;; [not sure what to do here.  -- rgr, 20-Nov-10.]
+	    (error "Oops; got buffers %S" buffers))
+	  (t
+	    ;; Single-buffer case.
+	    (switch-to-buffer-other-window (car buffers))
+	    ;; [should we go to one of these files?  should it be
+	    ;; the first, or the last?  -- rgr, 20-Nov-10.]
+	    (let* ((n-files (length files))
+		   (n-marked (vc-dir-set-marked-files files))
+		   (plural (if (= n-files 1) "" "s")))
+	      (if (= n-files n-marked)
+		  (message "Marked %d file%s." n-files plural)
+		  (message "Marked %d out of %d file%s."
+			   n-marked n-files plural)))))))
+
 (defun log-edit-insert-cvs-template ()
   "Insert the template specified by the CVS administrator, if any.
 This simply uses the local CVS/Template file."
diff --git a/lisp/vc/vc-dir.el b/lisp/vc/vc-dir.el
index 4397251..556c612 100644
--- a/lisp/vc/vc-dir.el
+++ b/lisp/vc/vc-dir.el
@@ -714,6 +714,31 @@ that share the same state."
   (interactive "e")
   (vc-dir-at-event e (vc-dir-mark-unmark 'vc-dir-toggle-mark-file)))
 
+(defun vc-dir-set-marked-files (files)
+  ;; Given a list of files, mark each file that appears in the list,
+  ;; and unmark all the others.  No mention is made if a file appears
+  ;; in the list that does not appear in the vc-dir buffer, but the
+  ;; number of files actually marked is returned.
+  (let ((crt (ewoc-nth vc-ewoc 0)) (n-files-marked 0))
+    (while crt
+      (let* ((file (ewoc-data crt))
+	     (new-mark-state
+	       (cond ((vc-dir-fileinfo->directory file)
+		       ;; Always unmark the directories.
+		       nil)
+		     ((let ((nodefile (vc-dir-fileinfo->name file)))
+			;; (message "[checking %S]" nodefile)
+			(member (expand-file-name nodefile) files))
+		       t))))
+	(unless (eq (not new-mark-state)
+		    (not (vc-dir-fileinfo->marked file)))
+	  (setf (vc-dir-fileinfo->marked file) new-mark-state)
+	  (ewoc-invalidate vc-ewoc crt)
+	  (when new-mark-state
+	    (incf n-files-marked))))
+      (setq crt (ewoc-next vc-ewoc crt)))
+    n-files-marked))
+
 (defun vc-dir-delete-file ()
   "Delete the marked files, or the current file if no marks."
   (interactive)
@@ -886,6 +911,45 @@ If it is a file, return the corresponding cons for the file itself."
 	      fileentries))
       (vc-dir-update fileentries (current-buffer)))))
 
+(defun vc-dir-find-buffer-for-file (file)
+  ;; Look for a vc-dir buffer that includes file, or one that might
+  ;; contain file if it were visible.  Returns nil if no such buffer
+  ;; was found, or a list of (buffer node) where node might be nil if
+  ;; file is not visible.
+  (message "checking %S for file %S" vc-dir-buffers file)
+  (let ((vc-dir-buffer nil) (vc-dir-default-directory-len 0)
+	(vc-dir-node nil) (tail vc-dir-buffers))
+    (while tail
+      (if (buffer-live-p (car tail))
+	  (with-current-buffer (car tail)
+	    ;; Search for a node for file.
+	    (let ((node (ewoc-nth vc-ewoc 0))
+		  (dd-len (length default-directory)))
+	      (while node
+		(let ((nodefile (vc-dir-fileinfo->name (ewoc-data node))))
+		  (if (string-equal (expand-file-name nodefile)
+				    file)
+		      ;; Success.
+		      (setq vc-dir-buffer (current-buffer)
+			    vc-dir-node node
+			    tail nil node nil)))
+		(setq node (ewoc-next vc-ewoc node)))
+	      ;; If not found, but the directory is a prefix of
+	      ;; file, then remember the buffer as a fallback.
+	      (if (and (null vc-dir-node)
+		       (> (length file) dd-len)
+		       (string-equal (substring file 0 dd-len)
+				     default-directory)
+		       ;; When we have multiple candidates, pick the one
+		       ;; deeper in the directory hierarchy.
+		       (or (null vc-dir-buffer)
+			   (> dd-len vc-dir-default-directory-len)))
+		  (setq vc-dir-buffer (current-buffer)
+			vc-dir-default-directory-len dd-len)))))
+      (setq tail (cdr tail)))
+    (and vc-dir-buffer
+	 (list vc-dir-buffer vc-dir-node))))
+
 (defun vc-dir-resynch-file (&optional fname)
   "Update the entries for FNAME in any directory buffers that list it."
   (let ((file (or fname (expand-file-name buffer-file-name)))



^ permalink raw reply related	[flat|nested] 8+ messages in thread

* Re: Updating *vc-dir* marks from *VC-log*
  2010-11-21  0:58 Updating *vc-dir* marks from *VC-log* Bob Rogers
@ 2010-11-21  4:46 ` Dan Nicolaescu
  2010-11-21 16:14   ` Bob Rogers
  2010-11-21 18:43 ` Stefan Monnier
  1 sibling, 1 reply; 8+ messages in thread
From: Dan Nicolaescu @ 2010-11-21  4:46 UTC (permalink / raw)
  To: Bob Rogers; +Cc: emacs-devel

Bob Rogers <rogers-emacs@rgrjr.dyndns.org> writes:

>    Perhaps I'm slow, but I only just noticed that it is possible to work
> on multiple VC commits for the same working copy in parallel, just by
> renaming *VC-log* buffers.  This is cool; it perfectly suits my working
> style.  I would like to write it up for the Emacs manual so that others
> can find it.
>
>    But it lacks something.  I often start a commit, then realize that
> I've left out a file or two, or maybe included one that ought to be
> committed separately.  When doing one commit at a time, this is a simple
> matter of returning to vc-dir, updating the set, and doing "C-x v v"
> again.  With multiple pending commits, what is needed is a way to return
> to vc-dir and "swap in" the log buffer fileset.  The patch below adds a
> new log-edit-visit-files-in-vc-dir command to do this.  I have
> tentatively bound it to "C-c @" in log-edit-mode, which I hope is
> sufficiently mnemonic for "mark".

I am not sure what you are trying to do here...
In the *VC log* buffer the vc-parent-buffer buffer-local variable
points to the *vc dir* buffer that was used to create it.
Doesn't this simplify what you are trying to do?



^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: Updating *vc-dir* marks from *VC-log*
  2010-11-21  4:46 ` Dan Nicolaescu
@ 2010-11-21 16:14   ` Bob Rogers
  2010-11-21 17:02     ` Dan Nicolaescu
  0 siblings, 1 reply; 8+ messages in thread
From: Bob Rogers @ 2010-11-21 16:14 UTC (permalink / raw)
  To: Dan Nicolaescu; +Cc: emacs-devel

   From: Dan Nicolaescu <dann@gnu.org>
   Date: Sat, 20 Nov 2010 23:46:40 -0500

   Bob Rogers <rogers-emacs@rgrjr.dyndns.org> writes:

   > . . . With multiple pending commits, what is needed is a way to return
   > to vc-dir and "swap in" the log buffer fileset.  The patch below adds a
   > new log-edit-visit-files-in-vc-dir command to do this.  I have
   > tentatively bound it to "C-c @" in log-edit-mode, which I hope is
   > sufficiently mnemonic for "mark".

   I am not sure what you are trying to do here...
   In the *VC log* buffer the vc-parent-buffer buffer-local variable
   points to the *vc dir* buffer that was used to create it.
   Doesn't this simplify what you are trying to do?

Hmm.  It could conceivably make vc-dir-find-buffer-for-file unnecessary.
(I had written that for another hack where vc-parent-buffer may not be
defined, or may not point to a vc-dir buffer, and just used it
unthinkingly here.)

   On the other hand, one would have to assume that users only want to
adjust the filesets of commits started from vc-dir buffers.
vc-dir-find-buffer-for-file would still be useful if the user originally
typed "C-x v v" in a file buffer, and then had second thoughts.

   But, at the very least, I ought to check vc-parent-buffer first,
since that would always DTRT if the file appears in multiple vc-dir
buffers.  Thanks for making that apparent.

   BTW, this is a subproject that came up while trying to make Emacs
smarter about changing marked files in vc-dir during the commit (see
bug#7350).  If the user does that, then Emacs should (a) ask her if she
wants to update the fileset if she types C-c C-c in the log buffer, and
(b) ask her if she wants to start a new commit or update the old one if
she types C-x v v in the vc-dir buffer.  Both of those involve updating
the fileset of an existing log buffer, so I probably need to address
that first.

					-- Bob



^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: Updating *vc-dir* marks from *VC-log*
  2010-11-21 16:14   ` Bob Rogers
@ 2010-11-21 17:02     ` Dan Nicolaescu
  2010-11-21 18:30       ` Bob Rogers
  0 siblings, 1 reply; 8+ messages in thread
From: Dan Nicolaescu @ 2010-11-21 17:02 UTC (permalink / raw)
  To: Bob Rogers; +Cc: emacs-devel

Bob Rogers <rogers-emacs@rgrjr.dyndns.org> writes:

>    From: Dan Nicolaescu <dann@gnu.org>
>    Date: Sat, 20 Nov 2010 23:46:40 -0500
>
>    Bob Rogers <rogers-emacs@rgrjr.dyndns.org> writes:
>
>    > . . . With multiple pending commits, what is needed is a way to return
>    > to vc-dir and "swap in" the log buffer fileset.  The patch below adds a
>    > new log-edit-visit-files-in-vc-dir command to do this.  I have
>    > tentatively bound it to "C-c @" in log-edit-mode, which I hope is
>    > sufficiently mnemonic for "mark".
>
>    I am not sure what you are trying to do here...
>    In the *VC log* buffer the vc-parent-buffer buffer-local variable
>    points to the *vc dir* buffer that was used to create it.
>    Doesn't this simplify what you are trying to do?
>
> Hmm.  It could conceivably make vc-dir-find-buffer-for-file unnecessary.
> (I had written that for another hack where vc-parent-buffer may not be
> defined, or may not point to a vc-dir buffer, and just used it
> unthinkingly here.)
>
>    On the other hand, one would have to assume that users only want to
> adjust the filesets of commits started from vc-dir buffers.
> vc-dir-find-buffer-for-file would still be useful if the user originally
> typed "C-x v v" in a file buffer, and then had second thoughts.

It's still unclear what you are trying to do, could you please
describe in detail the use-case you have in mind?

>
>    But, at the very least, I ought to check vc-parent-buffer first,
> since that would always DTRT if the file appears in multiple vc-dir
> buffers.  Thanks for making that apparent.
>
>    BTW, this is a subproject that came up while trying to make Emacs
> smarter about changing marked files in vc-dir during the commit (see
> bug#7350).  

That's quite easy (I have it in my local copy).
`log-edit-files' gives you a list of files that *VC log* would check in.
`vc-deduce-fileset' in `vc-parent-buffer' gives you the currently selected files in *vc dir*



^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: Updating *vc-dir* marks from *VC-log*
  2010-11-21 17:02     ` Dan Nicolaescu
@ 2010-11-21 18:30       ` Bob Rogers
  2010-11-23 17:06         ` Dan Nicolaescu
  0 siblings, 1 reply; 8+ messages in thread
From: Bob Rogers @ 2010-11-21 18:30 UTC (permalink / raw)
  To: Dan Nicolaescu; +Cc: emacs-devel

   From: Dan Nicolaescu <dann@gnu.org>
   Date: Sun, 21 Nov 2010 12:02:19 -0500

   It's still unclear what you are trying to do, could you please
   describe in detail the use-case you have in mind?

Here's what I often find myself wanting to do:

   1.  Start a multi-file commit from vc-dir.

   2.  After writing half the log buffer, realize that one or two of the
files scheduled for commit are independent of the others, and should
really be committed first, in a separate operation.

   3.  Go back to *vc-dir*, change the mark set to include only those
files, and commit using a new log buffer.

   4.  Re-visit the first log buffer and finish the original commit,
with a reduced fileset.

   Currently, I either have to (a) save the current log buffer contents
somewhere and start fresh, or (b) drop the file(s) from the first commit
and just do them in the reverse order.  (It might work to rename the log
buffer at step 2, and then rename it back; I haven't tried that.  But I
was shooting for something more transparent.)

   FWIW, I used to have a hack that supported this workflow by splitting
log buffers in two, but it was driven by file names in the log buffer
itself, which wasn't very clean.  (And it was part of another multi-file
commit hack, before Emacs had proper support for it.)

   >    But, at the very least, I ought to check vc-parent-buffer first,
   > since that would always DTRT if the file appears in multiple vc-dir
   > buffers.  Thanks for making that apparent.
   >
   >    BTW, this is a subproject that came up while trying to make Emacs
   > smarter about changing marked files in vc-dir during the commit (see
   > bug#7350).  

   That's quite easy (I have it in my local copy).  `log-edit-files'
   gives you a list of files that *VC log* would check in.
   `vc-deduce-fileset' in `vc-parent-buffer' gives you the currently
   selected files in *vc dir*

All true.  But Stefan pointed out in response to bug#7350 that C-c C-c
should at least bring it to the user's attention if those two sets
differ, and update the commit fileset if the use approves.

   But if you've already have that code in your local copy, then I don't
have to write it.  Right?

					-- Bob



^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: Updating *vc-dir* marks from *VC-log*
  2010-11-21  0:58 Updating *vc-dir* marks from *VC-log* Bob Rogers
  2010-11-21  4:46 ` Dan Nicolaescu
@ 2010-11-21 18:43 ` Stefan Monnier
  2010-11-21 20:46   ` Bob Rogers
  1 sibling, 1 reply; 8+ messages in thread
From: Stefan Monnier @ 2010-11-21 18:43 UTC (permalink / raw)
  To: Bob Rogers; +Cc: emacs-devel

>    Perhaps I'm slow, but I only just noticed that it is possible to work
> on multiple VC commits for the same working copy in parallel, just by
> renaming *VC-log* buffers.  This is cool; it perfectly suits my working
> style.  I would like to write it up for the Emacs manual so that others
> can find it.

Hmm... I'd like to change VC-Log so that it always commits what's
selected in vc-dir at the time of the commit rather than at the time the
VC-Log buffer is opened (with a confirmation prompt to the user when the
two sets are actually different).

In the common case where the user only uses a single VC-Log buffer, it
is better than the current situation since it makes your
log-edit-visit-files-in-vc-dir completely unnecessary.

But I'm not sure how to best handle your use case where you have several
VC-Log buffers, then.


        Stefan



^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: Updating *vc-dir* marks from *VC-log*
  2010-11-21 18:43 ` Stefan Monnier
@ 2010-11-21 20:46   ` Bob Rogers
  0 siblings, 0 replies; 8+ messages in thread
From: Bob Rogers @ 2010-11-21 20:46 UTC (permalink / raw)
  To: Stefan Monnier; +Cc: emacs-devel

   From: Stefan Monnier <monnier@iro.umontreal.ca>
   Date: Sun, 21 Nov 2010 13:43:19 -0500

   >    Perhaps I'm slow, but I only just noticed that it is possible to work
   > on multiple VC commits for the same working copy in parallel, just by
   > renaming *VC-log* buffers.  This is cool; it perfectly suits my working
   > style.  I would like to write it up for the Emacs manual so that others
   > can find it.

   Hmm... I'd like to change VC-Log so that it always commits what's
   selected in vc-dir at the time of the commit rather than at the time the
   VC-Log buffer is opened (with a confirmation prompt to the user when the
   two sets are actually different).

Yes, that's what I thought you meant.  (But I was thinking of going
further, such that if the user refuses the "Use new fileset?" prompt,
there is a followup "Commit current fileset?" prompt.  That preserves
access to existing behavior, though it does make an exception to the
"always commits" rule you have stated.)

   In the common case where the user only uses a single VC-Log buffer, it
   is better than the current situation since it makes your
   log-edit-visit-files-in-vc-dir completely unnecessary.

That is mostly true.  The difference is that
log-edit-visit-files-in-vc-dir also works to change the fileset of a
commit that starts from a single file.  You can use vc-dir for that
purpose by doing an explicit C-x v v in *vc-dir* to hijack the existing
single-file log buffer, but that is not obvious.  And if the user
doesn't C-x v v from *vc-dir*, then C-c C-c won't DTRT, because it won't
know about *vc-dir*.

   And it would also be convenient to have a log-edit-mode command that
takes you back to the right *vc-dir* buffer.  Of course, that's a much
simpler command than log-edit-visit-files-in-vc-dir.  Would that be
preferable?

   But I'm not sure how to best handle your use case where you have several
   VC-Log buffers, then.

	   Stefan

Then perhaps we should table this discussion until the "Use new
fileset?" prompt is in place.

					-- Bob



^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: Updating *vc-dir* marks from *VC-log*
  2010-11-21 18:30       ` Bob Rogers
@ 2010-11-23 17:06         ` Dan Nicolaescu
  0 siblings, 0 replies; 8+ messages in thread
From: Dan Nicolaescu @ 2010-11-23 17:06 UTC (permalink / raw)
  To: Bob Rogers; +Cc: emacs-devel

Bob Rogers <rogers-emacs@rgrjr.dyndns.org> writes:

> All true.  But Stefan pointed out in response to bug#7350 that C-c C-c
> should at least bring it to the user's attention if those two sets
> differ, and update the commit fileset if the use approves.
>
>    But if you've already have that code in your local copy, then I don't
> have to write it.  Right?

Don't hold your breath, I mostly gave up on checking in my VC changes,
the overhead is just not worth it.



^ permalink raw reply	[flat|nested] 8+ messages in thread

end of thread, other threads:[~2010-11-23 17:06 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2010-11-21  0:58 Updating *vc-dir* marks from *VC-log* Bob Rogers
2010-11-21  4:46 ` Dan Nicolaescu
2010-11-21 16:14   ` Bob Rogers
2010-11-21 17:02     ` Dan Nicolaescu
2010-11-21 18:30       ` Bob Rogers
2010-11-23 17:06         ` Dan Nicolaescu
2010-11-21 18:43 ` Stefan Monnier
2010-11-21 20:46   ` Bob Rogers

Code repositories for project(s) associated with this public inbox

	https://git.savannah.gnu.org/cgit/emacs.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).