* [PATCH] Allow abbreviations in the first refspec to be merged
From: Daniel Barkalow @ 2007-09-28 23:34 UTC (permalink / raw)
To: Junio C Hamano; +Cc: git
The config item for a refspec side and the ref name that it matches
aren't necessarily character-for-character identical. We actually want
to merge a ref by default if: there is no per-branch config, it is the
found result of looking for the match for the first refspec, and the
first refspec is not a pattern. Beyond that, anything that
get_fetch_map() thinks matches is fine.
Signed-off-by: Daniel Barkalow <barkalow@iabervon.org>
---
This fixes the configuration you gave for me, and passes all the
usual tests.
builtin-fetch.c | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/builtin-fetch.c b/builtin-fetch.c
index 2f639cc..ac68ff5 100644
--- a/builtin-fetch.c
+++ b/builtin-fetch.c
@@ -102,7 +102,7 @@ static struct ref *get_ref_map(struct transport *transport,
remote->fetch[i].dst[0])
*autotags = 1;
if (!i && !has_merge && ref_map &&
- !strcmp(remote->fetch[0].src, ref_map->name))
+ !remote->fetch[0].pattern)
ref_map->merge = 1;
}
if (has_merge)
--
1.5.3.2.1107.ge9eab8-dirty
^ permalink raw reply related
* Re: [PATCH] Allow abbreviations in the first refspec to be merged
From: Shawn O. Pearce @ 2007-09-28 23:38 UTC (permalink / raw)
To: Daniel Barkalow; +Cc: Junio C Hamano, git
In-Reply-To: <Pine.LNX.4.64.0709281932550.5926@iabervon.org>
Daniel Barkalow <barkalow@iabervon.org> wrote:
> The config item for a refspec side and the ref name that it matches
> aren't necessarily character-for-character identical.
[snip]
> diff --git a/builtin-fetch.c b/builtin-fetch.c
> index 2f639cc..ac68ff5 100644
> --- a/builtin-fetch.c
> +++ b/builtin-fetch.c
> @@ -102,7 +102,7 @@ static struct ref *get_ref_map(struct transport *transport,
> remote->fetch[i].dst[0])
> *autotags = 1;
> if (!i && !has_merge && ref_map &&
> - !strcmp(remote->fetch[0].src, ref_map->name))
> + !remote->fetch[0].pattern)
> ref_map->merge = 1;
> }
> if (has_merge)
Ooooooooooooh. Of course. That makes perfect sense now that I
see your explanation and patch. Thanks for fixing that! :-)
--
Shawn.
^ permalink raw reply
* Re: A tour of git: the basics (and notes on some unfriendly messages)
From: Shawn O. Pearce @ 2007-09-29 0:00 UTC (permalink / raw)
To: Carl Worth; +Cc: git
In-Reply-To: <87ir5us82a.wl%cworth@cworth.org>
Carl Worth <cworth@cworth.org> wrote:
> I recently "ported" the introductory chapter of Bryan O’Sullivan's
> Distributed revision control with Mercurial[1] from mercurial to
> git. The result is here:
>
> A tour of git: the basics
> http://cworth.org/hgbook-git/tour/
Interesting.
> * Is "git help" actually a builtin thing or just a way to call out to
> "man"? Does it work at all in Windows ports of git, for example?
> (OK, so that one's just a question, not an issue it git)
`git help` with no arguments displays a message compiled into git.
`git help init` runs `man git-init`. If you don't have any manual
pages installed, or if they aren't available to your man installation
then it fails with "No manual entry for git-init" or whatever your
local man implementation dumps.
Brett Schwartz started an asciidoc viewer for Tcl/Tk that I am still
playing around with and trying to get working right in git-gui.
In theory one could use that to display the manual right from the
asciidoc files, thus bypassing the need for asciidoc and xmlto.
On Cygwin we have man, so `git help init` (or `git init --help`) work
just fine to display the manual entry. No idea about the MSYS port.
> * The output from a git-clone operating locally is really confusing:
>
> $ git clone hello hello-clone
> Initialized empty Git repository in /tmp/hello-clone/.git/
> 0 blocks
>
> Empty? Didn't I just clone it? What does "0 blocks" mean?
Yea. That's because we realized its on the local disk and used
`cpio` with hardlinks to copy the files. So cpio says it copied
0 blocks as it actually just hardlinked everything for you. No
data was actually copied.
git-gui's new clone UI uses fancy progress meters here and tries
to shield the user from "plumbing and UNIX tools" spitting out
seemingly nonsense messages. We probably should try harder in
git-clone to do the same here.
> * git-log by default displays "Date" that is the author date, but
> also only uses committer date for options such as --since. This is
> confusing.
I've never thought about that. But when you say it I think its very
obvious that it could be confusing to a new user. Maybe we should
show the committer line and its date if it doesn't match the author
name/date. Usually I don't care who committed a change in git.git
(its a very small handful of people that Junio pulls from directly)
but at day-job committer name is usually just as interesting as
the author name *when they aren't the same*.
> * There's a ton of extraneous output from git-fetch. I would love to
> see it reduced to a single-line progress bar, (even if a
> multiple-staged progress bar). I'm imagining a final line
> something like:
>
> Computing (100%) Transferring (100%)
>
> But you can imagine more accurate words than those, (I'm not even
> sure what all of the things mean that git-fetch is currently
> reporting progress on).
Yea. About half of that output is from pack-objects and either
unpack-objects or index-pack. The other part is from git-fetch
itself as it updates the local tracking branches (if any are to be
updated). Now that git-fetch is in C and reasonably stable maybe
I can look into making this prettier. Few people really grok the
pack-objects/index-pack output, nor do they care. They just want
to know two things:
- Is git working or frozen in limbo?
- Is git frozen because my network sucks, or git sucks?
- When will this be done? Please $DIETY, I want to go home!
Make the fetch finish!
The C based git-fetch made the http protocol almost totally silent.
(No more got/walk messages.) But that's actually also bad as it
now doesn't even let you know its transferring anything at all.
There are serious issues here about getting the user the progress
they really want. The last item ("When will this be done?") is
actually not possible to determine under either the native git
protocol or HTTP/FTP. We have no idea up front how much data must
be transferred. In the native git case we do know how many objects,
but we don't know how many bytes that will be. It could be under
a kilobyte in one project. That same object count for a different
set of objects fetch could be 500M. Radically different transfer
times would be required.
--
Shawn.
^ permalink raw reply
* [PATCH v3 2/2] fetch/push: readd rsync support
From: Johannes Schindelin @ 2007-09-29 0:35 UTC (permalink / raw)
To: Junio C Hamano, spearce; +Cc: Daniel Barkalow, git
In-Reply-To: <7vtzpeo5ar.fsf@gitster.siamese.dyndns.org>
We lost rsync support when transitioning from shell to C. Support it
again (even if the transport is technically deprecated, some people just
do not have any chance to use anything else).
Also, add a test to t5510. Since rsync transport is not configured by
default on most machines, and especially not such that you can
write to rsync://127.0.0.1$(pwd)/, it is disabled by default; you can
enable it by setting the environment variable TEST_RSYNC.
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
---
Sorry for the borked v2 of this patch...
I cleaned up some other parts, such as free()ing or close()ing
also in case of an error.
t/t5510-fetch.sh | 35 ++++++
transport.c | 328 +++++++++++++++++++++++++++++++++++++++++++++++++++++-
2 files changed, 362 insertions(+), 1 deletions(-)
diff --git a/t/t5510-fetch.sh b/t/t5510-fetch.sh
index 439430f..73a4e3c 100755
--- a/t/t5510-fetch.sh
+++ b/t/t5510-fetch.sh
@@ -153,4 +153,39 @@ test_expect_success 'bundle should be able to create a full history' '
'
+test "$TEST_RSYNC" && {
+test_expect_success 'fetch via rsync' '
+ git pack-refs &&
+ mkdir rsynced &&
+ cd rsynced &&
+ git init &&
+ git fetch rsync://127.0.0.1$(pwd)/../.git master:refs/heads/master &&
+ git gc --prune &&
+ test $(git rev-parse master) = $(cd .. && git rev-parse master) &&
+ git fsck --full
+'
+
+test_expect_success 'push via rsync' '
+ mkdir ../rsynced2 &&
+ (cd ../rsynced2 &&
+ git init) &&
+ git push rsync://127.0.0.1$(pwd)/../rsynced2/.git master &&
+ cd ../rsynced2 &&
+ git gc --prune &&
+ test $(git rev-parse master) = $(cd .. && git rev-parse master) &&
+ git fsck --full
+'
+
+test_expect_success 'push via rsync' '
+ cd .. &&
+ mkdir rsynced3 &&
+ (cd rsynced3 &&
+ git init) &&
+ git push --all rsync://127.0.0.1$(pwd)/rsynced3/.git &&
+ cd rsynced3 &&
+ test $(git rev-parse master) = $(cd .. && git rev-parse master) &&
+ git fsck --full
+'
+}
+
test_done
diff --git a/transport.c b/transport.c
index 4f9cddc..a2ee8f3 100644
--- a/transport.c
+++ b/transport.c
@@ -6,6 +6,330 @@
#include "fetch-pack.h"
#include "walker.h"
#include "bundle.h"
+#include "dir.h"
+#include "refs.h"
+
+/* rsync support */
+
+/*
+ * We copy packed-refs and refs/ into a temporary file, then read the
+ * loose refs recursively (sorting whenever possible), and then inserting
+ * those packed refs that are not yet in the list (not validating, but
+ * assuming that the file is sorted).
+ *
+ * Appears refactoring this from refs.c is too cumbersome.
+ */
+
+static int str_cmp(const void *a, const void *b)
+{
+ const char *s1 = a;
+ const char *s2 = b;
+
+ return strcmp(s1, s2);
+}
+
+/* path->buf + name_offset is expected to point to "refs/" */
+
+static int read_loose_refs(struct strbuf *path, int name_offset,
+ struct ref **tail)
+{
+ DIR *dir = opendir(path->buf);
+ struct dirent *de;
+ struct {
+ char **entries;
+ int nr, alloc;
+ } list;
+ int i, pathlen;
+
+ if (!dir)
+ return -1;
+
+ memset (&list, 0, sizeof(list));
+
+ while ((de = readdir(dir))) {
+ if (de->d_name[0] == '.' && (de->d_name[1] == '\0' ||
+ (de->d_name[1] == '.' &&
+ de->d_name[2] == '\0')))
+ continue;
+ ALLOC_GROW(list.entries, list.nr + 1, list.alloc);
+ list.entries[list.nr++] = xstrdup(de->d_name);
+ }
+ closedir(dir);
+
+ /* sort the list */
+
+ qsort(list.entries, list.nr, sizeof(char *), str_cmp);
+
+ pathlen = path->len;
+ strbuf_addch(path, '/');
+
+ for (i = 0; i < list.nr; i++, strbuf_setlen(path, pathlen + 1)) {
+ strbuf_addstr(path, list.entries[i]);
+ if (read_loose_refs(path, name_offset, tail)) {
+ int fd = open(path->buf, O_RDONLY);
+ char buffer[40];
+ struct ref *next;
+
+ if (fd < 0)
+ continue;
+ next = alloc_ref(path->len - name_offset + 1);
+ if (read_in_full(fd, buffer, 40) != 40 ||
+ get_sha1_hex(buffer, next->old_sha1)) {
+ close(fd);
+ free(next);
+ continue;
+ }
+ close(fd);
+ strcpy(next->name, path->buf + name_offset);
+ (*tail)->next = next;
+ *tail = next;
+ }
+ }
+ strbuf_setlen(path, pathlen);
+
+ for (i = 0; i < list.nr; i++)
+ free(list.entries[i]);
+ free(list.entries);
+
+ return 0;
+}
+
+/* insert the packed refs for which no loose refs were found */
+
+static void insert_packed_refs(const char *packed_refs, struct ref **list)
+{
+ FILE *f = fopen(packed_refs, "r");
+ static char buffer[PATH_MAX];
+
+ if (!f)
+ return;
+
+ for (;;) {
+ int cmp, len;
+
+ if (!fgets(buffer, sizeof(buffer), f)) {
+ fclose(f);
+ return;
+ }
+
+ if (hexval(buffer[0]) > 0xf)
+ continue;
+ len = strlen(buffer);
+ if (buffer[len - 1] == '\n')
+ buffer[--len] = '\0';
+ if (len < 41)
+ continue;
+ while ((*list)->next &&
+ (cmp = strcmp(buffer + 41,
+ (*list)->next->name)) > 0)
+ list = &(*list)->next;
+ if (!(*list)->next || cmp < 0) {
+ struct ref *next = alloc_ref(len - 40);
+ buffer[40] = '\0';
+ if (get_sha1_hex(buffer, next->old_sha1)) {
+ warning ("invalid SHA-1: %s", buffer);
+ free(next);
+ continue;
+ }
+ strcpy(next->name, buffer + 41);
+ next->next = (*list)->next;
+ (*list)->next = next;
+ list = &(*list)->next;
+ }
+ }
+}
+
+static struct ref *get_refs_via_rsync(const struct transport *transport)
+{
+ struct strbuf buf = STRBUF_INIT, temp_dir = STRBUF_INIT;
+ struct ref dummy, *tail = &dummy;
+ struct child_process rsync;
+ const char *args[5];
+ int temp_dir_len;
+
+ /* copy the refs to the temporary directory */
+
+ strbuf_addstr(&temp_dir, git_path("rsync-refs-XXXXXX"));
+ if (!mkdtemp(temp_dir.buf))
+ die ("Could not make temporary directory");
+ temp_dir_len = temp_dir.len;
+
+ strbuf_addstr(&buf, transport->url);
+ strbuf_addstr(&buf, "/refs");
+
+ memset(&rsync, 0, sizeof(rsync));
+ rsync.argv = args;
+ rsync.stdout_to_stderr = 1;
+ args[0] = "rsync";
+ args[1] = transport->verbose ? "-rv" : "-r";
+ args[2] = buf.buf;
+ args[3] = temp_dir.buf;
+ args[4] = NULL;
+
+ if (run_command(&rsync))
+ die ("Could not run rsync to get refs");
+
+ strbuf_reset(&buf);
+ strbuf_addstr(&buf, transport->url);
+ strbuf_addstr(&buf, "/packed-refs");
+
+ args[2] = buf.buf;
+
+ if (run_command(&rsync))
+ die ("Could not run rsync to get refs");
+
+ /* read the copied refs */
+
+ strbuf_addstr(&temp_dir, "/refs");
+ read_loose_refs(&temp_dir, temp_dir_len + 1, &tail);
+ strbuf_setlen(&temp_dir, temp_dir_len);
+
+ tail = &dummy;
+ strbuf_addstr(&temp_dir, "/packed-refs");
+ insert_packed_refs(temp_dir.buf, &tail);
+ strbuf_setlen(&temp_dir, temp_dir_len);
+
+ if (remove_dir_recursively(&temp_dir, 0))
+ warning ("Error removing temporary directory %s.",
+ temp_dir.buf);
+
+ strbuf_release(&buf);
+ strbuf_release(&temp_dir);
+
+ return dummy.next;
+}
+
+static int fetch_objs_via_rsync(struct transport *transport,
+ int nr_objs, struct ref **to_fetch)
+{
+ struct strbuf buf = STRBUF_INIT;
+ struct child_process rsync;
+ const char *args[8];
+ int result;
+
+ strbuf_addstr(&buf, transport->url);
+ strbuf_addstr(&buf, "/objects/");
+
+ memset(&rsync, 0, sizeof(rsync));
+ rsync.argv = args;
+ rsync.stdout_to_stderr = 1;
+ args[0] = "rsync";
+ args[1] = transport->verbose ? "-rv" : "-r";
+ args[2] = "--ignore-existing";
+ args[3] = "--exclude";
+ args[4] = "info";
+ args[5] = buf.buf;
+ args[6] = get_object_directory();
+ args[7] = NULL;
+
+ /* NEEDSWORK: handle one level of alternates */
+ result = run_command(&rsync);
+
+ strbuf_release(&buf);
+
+ return result;
+}
+
+static int write_one_ref(const char *name, const unsigned char *sha1,
+ int flags, void *data)
+{
+ struct strbuf *buf = data;
+ int len = buf->len;
+ FILE *f;
+
+ /* when called via for_each_ref(), flags is non-zero */
+ if (flags && prefixcmp(name, "refs/heads/") &&
+ prefixcmp(name, "refs/tags/"))
+ return 0;
+
+ strbuf_addstr(buf, name);
+ if (safe_create_leading_directories(buf->buf) ||
+ !(f = fopen(buf->buf, "w")) ||
+ fprintf(f, "%s\n", sha1_to_hex(sha1)) < 0 ||
+ fclose(f))
+ return error("problems writing temporary file %s", buf->buf);
+ strbuf_setlen(buf, len);
+ return 0;
+}
+
+static int write_refs_to_temp_dir(struct strbuf *temp_dir,
+ int refspec_nr, const char **refspec)
+{
+ int i;
+
+ for (i = 0; i < refspec_nr; i++) {
+ unsigned char sha1[20];
+ char *ref;
+
+ if (dwim_ref(refspec[i], strlen(refspec[i]), sha1, &ref) != 1)
+ return error("Could not get ref %s", refspec[i]);
+
+ if (write_one_ref(ref, sha1, 0, temp_dir)) {
+ free(ref);
+ return -1;
+ }
+ free(ref);
+ }
+ return 0;
+}
+
+static int rsync_transport_push(struct transport *transport,
+ int refspec_nr, const char **refspec, int flags)
+{
+ struct strbuf buf = STRBUF_INIT, temp_dir = STRBUF_INIT;
+ int result = 0, i;
+ struct child_process rsync;
+ const char *args[8];
+
+ /* first push the objects */
+
+ strbuf_addstr(&buf, transport->url);
+ strbuf_addch(&buf, '/');
+
+ memset(&rsync, 0, sizeof(rsync));
+ rsync.argv = args;
+ rsync.stdout_to_stderr = 1;
+ args[0] = "rsync";
+ args[1] = transport->verbose ? "-av" : "-a";
+ args[2] = "--ignore-existing";
+ args[3] = "--exclude";
+ args[4] = "info";
+ args[5] = get_object_directory();;
+ args[6] = buf.buf;
+ args[7] = NULL;
+
+ if (run_command(&rsync))
+ return error("Could not push objects to %s", transport->url);
+
+ /* copy the refs to the temporary directory; they could be packed. */
+
+ strbuf_addstr(&temp_dir, git_path("rsync-refs-XXXXXX"));
+ if (!mkdtemp(temp_dir.buf))
+ die ("Could not make temporary directory");
+ strbuf_addch(&temp_dir, '/');
+
+ if (flags & TRANSPORT_PUSH_ALL) {
+ if (for_each_ref(write_one_ref, &temp_dir))
+ return -1;
+ } else if (write_refs_to_temp_dir(&temp_dir, refspec_nr, refspec))
+ return -1;
+
+ i = (flags & TRANSPORT_PUSH_FORCE) ? 2 : 3;
+ args[i++] = temp_dir.buf;
+ args[i++] = transport->url;
+ args[i++] = NULL;
+ if (run_command(&rsync))
+ result = error("Could not push to %s", transport->url);
+
+ if (remove_dir_recursively(&temp_dir, 0))
+ warning ("Could not remove temporary directory %s.",
+ temp_dir.buf);
+
+ strbuf_release(&buf);
+ strbuf_release(&temp_dir);
+
+ return result;
+}
/* Generic functions for using commit walkers */
@@ -402,7 +726,9 @@ struct transport *transport_get(struct remote *remote, const char *url)
ret->url = url;
if (!prefixcmp(url, "rsync://")) {
- /* not supported; don't populate any ops */
+ ret->get_refs_list = get_refs_via_rsync;
+ ret->fetch = fetch_objs_via_rsync;
+ ret->push = rsync_transport_push;
} else if (!prefixcmp(url, "http://")
|| !prefixcmp(url, "https://")
--
1.5.3.2.1102.g9487
^ permalink raw reply related
* Re: A tour of git: the basics (and notes on some unfriendly messages)
From: Junio C Hamano @ 2007-09-29 0:45 UTC (permalink / raw)
To: Carl Worth; +Cc: git
In-Reply-To: <87ir5us82a.wl%cworth@cworth.org>
Thanks for starting this. It was an interesting read.
----------------------------------------------------------------
#2.2.1
"git help init" would give man page. The time when the short
help is given is when you mistype options, as in:
$ git init --huh?
#2.4
By default this command prints a brief paragraph of output...
Not really. The default is to give you the entire log message,
unless you somehow made --pretty=short the default with your
copy of git.
The "git log" tool doesn't display the Committer...
You can ask it to, so "by default" is missing.
#2.7.1
But some poepl, (notably Linus...
typo.
#2.7.6
for which "git commit --amend" was
was what? "invented" perhaps?
#2.8.3
Using "git remote" to pull changes other repositories
"changes from other repositories".
----------------------------------------------------------------
^ permalink raw reply
* Re: A tour of git: the basics (and notes on some unfriendly messages)
From: Johannes Schindelin @ 2007-09-29 0:49 UTC (permalink / raw)
To: Shawn O. Pearce; +Cc: Carl Worth, git
In-Reply-To: <20070929000056.GZ3099@spearce.org>
Hi,
On Fri, 28 Sep 2007, Shawn O. Pearce wrote:
> On Cygwin we have man, so `git help init` (or `git init --help`) work
> just fine to display the manual entry. No idea about the MSYS port.
We open the html pages. That is, we don't yet, since we do not generate
the html pages just yet; asciidoc is a Python program, and Python is not
available as an MSys program as far as I know (and asciidoc insists on
finding files in a Unix-like file structure, so we _do_ need an MSys
Python).
... but all this would be easier if we succeeded in having a minimal
asciidoc lookalike in git.git...
> > * The output from a git-clone operating locally is really confusing:
> >
> > $ git clone hello hello-clone
> > Initialized empty Git repository in /tmp/hello-clone/.git/
> > 0 blocks
> >
> > Empty? Didn't I just clone it? What does "0 blocks" mean?
>
> Yea. That's because we realized its on the local disk and used
> `cpio` with hardlinks to copy the files. So cpio says it copied
> 0 blocks as it actually just hardlinked everything for you. No
> data was actually copied.
>
> git-gui's new clone UI uses fancy progress meters here and tries
> to shield the user from "plumbing and UNIX tools" spitting out
> seemingly nonsense messages. We probably should try harder in
> git-clone to do the same here.
AFAICT git-clone is a prime candidate for builtinification, after which
issues like this should be easy to address.
> > * git-log by default displays "Date" that is the author date, but
> > also only uses committer date for options such as --since. This is
> > confusing.
>
> I've never thought about that. But when you say it I think its very
> obvious that it could be confusing to a new user. Maybe we should show
> the committer line and its date if it doesn't match the author
> name/date. Usually I don't care who committed a change in git.git (its
> a very small handful of people that Junio pulls from directly) but at
> day-job committer name is usually just as interesting as the author name
> *when they aren't the same*.
--pretty=fuller
Ciao,
Dscho
^ permalink raw reply
* Re: Use of strbuf.buf when strbuf.len == 0
From: Linus Torvalds @ 2007-09-29 0:51 UTC (permalink / raw)
To: Pierre Habouzit; +Cc: Junio C Hamano, git
In-Reply-To: <20070927101300.GD10289@artemis.corp>
On Thu, 27 Sep 2007, Pierre Habouzit wrote:
>
> I can see a way, that would need special proof-reading of the strbuf
> module, but should not harm its users, that would be to change
> STRBUF_INIT to work this way:
>
> { .buf = "", .len = 0, .alloc = 0 }
I'd like to pipe up a bit here..
I think the above is a good fix for the current problem of wanting to
always be able to use "sb->buf", but I thinkit actually has the potential
to fix another issue entirely.
Namely strbuf's that are initialized from various static strings and/or
strings not directly allocated with malloc().
That's not necessarily something really unusual. Wanting to initialize a
string with a fixed constant value is a common problem.
And wouldn't it be nice if you could actually do that, with
{ .buf = "static initializer", .len = 18, .alloc = 0 }
and have all the strbuf routines that modify the initializer (including
making it shorter!) notice that the allocation is too short, and create a
new allocation?
Hmm?
Linus
^ permalink raw reply
* [PATCH] rebase -i: support single-letter abbreviations for the actions
From: Johannes Schindelin @ 2007-09-29 1:31 UTC (permalink / raw)
To: gitster, git
When you do many rebases, you can get annoyed by having to type out
the actions "edit" or "squash" in total.
This commit helps that, by allowing you to enter "e" instead of "edit",
or "s" instead of "squash", and it also plays nice with "merge" or "amend"
as synonyms to "squash".
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
---
git-rebase--interactive.sh | 8 ++++----
1 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/git-rebase--interactive.sh b/git-rebase--interactive.sh
index 823291d..0f9483e 100755
--- a/git-rebase--interactive.sh
+++ b/git-rebase--interactive.sh
@@ -232,14 +232,14 @@ do_next () {
'#'*|'')
mark_action_done
;;
- pick)
+ pick|p)
comment_for_reflog pick
mark_action_done
pick_one $sha1 ||
die_with_patch $sha1 "Could not apply $sha1... $rest"
;;
- edit)
+ edit|e)
comment_for_reflog edit
mark_action_done
@@ -254,7 +254,7 @@ do_next () {
warn
exit 0
;;
- squash)
+ squash|s|merge|m|amend|a)
comment_for_reflog squash
has_action "$DONE" ||
@@ -263,7 +263,7 @@ do_next () {
mark_action_done
make_squash_message $sha1 > "$MSG"
case "$(peek_next_command)" in
- squash)
+ squash|s|merge|m|amend|a)
EDIT_COMMIT=
USE_OUTPUT=output
cp "$MSG" "$SQUASH_MSG"
--
1.5.3.2.1102.g9487
^ permalink raw reply related
* Re: [PATCH] rebase -i: support single-letter abbreviations for the actions
From: Junio C Hamano @ 2007-09-29 2:12 UTC (permalink / raw)
To: Johannes Schindelin; +Cc: gitster, git
In-Reply-To: <Pine.LNX.4.64.0709290231300.28395@racer.site>
Johannes Schindelin <Johannes.Schindelin@gmx.de> writes:
> When you do many rebases, you can get annoyed by having to type out
> the actions "edit" or "squash" in total.
>
> This commit helps that, by allowing you to enter "e" instead of "edit",
> or "s" instead of "squash", and it also plays nice with "merge" or "amend"
> as synonyms to "squash".
I am not sure if we want to taint the words merge and amend like
this. I was hoping someday you would allow people to reorder
something like this...
e
\
---a---b---c---d
into something like this:
e
\
---b'--c'--a'+d'
The insn sequence you prepare for the user to edit would be:
pick a
pick b
merge c
pick d
and then the user would rewrite that to:
pick b
merge c
pick a
squash d
I do not think making 'amend' a synonym to 'squash' is correct
either; isn't it closer to 'edit'?
I however do agree that giving short-hand would be a good idea.
^ permalink raw reply
* [PATCH v2] rebase -i: support single-letter abbreviations for the actions
From: Johannes Schindelin @ 2007-09-29 2:32 UTC (permalink / raw)
To: Junio C Hamano; +Cc: git
In-Reply-To: <7vfy0ymd7g.fsf@gitster.siamese.dyndns.org>
When you do many rebases, you can get annoyed by having to type out
the actions "edit" or "squash" in total.
This commit helps that, by allowing you to enter "e" instead of "edit",
"p" instead of "pick", or "s" instead of "squash".
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
---
On Fri, 28 Sep 2007, Junio C Hamano wrote:
> I am not sure if we want to taint the words merge and amend like
> this. I was hoping someday you would allow people to reorder
> something like this...
Okay, you convinced me.
>
> e
> \
> ---a---b---c---d
>
> into something like this:
>
> e
> \
> ---b'--c'--a'+d'
I thought that this would be possible with "git rebase -p -i"?
Ah no, that does not work; "-p" is not yet graceful enough to
accept reorders. (But then, I do not see why the command should
be "merge" instead of the "pick" we already have...)
git-rebase--interactive.sh | 8 ++++----
1 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/git-rebase--interactive.sh b/git-rebase--interactive.sh
index 823291d..7a5aaa5 100755
--- a/git-rebase--interactive.sh
+++ b/git-rebase--interactive.sh
@@ -232,14 +232,14 @@ do_next () {
'#'*|'')
mark_action_done
;;
- pick)
+ pick|p)
comment_for_reflog pick
mark_action_done
pick_one $sha1 ||
die_with_patch $sha1 "Could not apply $sha1... $rest"
;;
- edit)
+ edit|e)
comment_for_reflog edit
mark_action_done
@@ -254,7 +254,7 @@ do_next () {
warn
exit 0
;;
- squash)
+ squash|s)
comment_for_reflog squash
has_action "$DONE" ||
@@ -263,7 +263,7 @@ do_next () {
mark_action_done
make_squash_message $sha1 > "$MSG"
case "$(peek_next_command)" in
- squash)
+ squash|s)
EDIT_COMMIT=
USE_OUTPUT=output
cp "$MSG" "$SQUASH_MSG"
--
1.5.3.2.1102.g9487
^ permalink raw reply related
* Re: A tour of git: the basics (and notes on some unfriendly messages)
From: Nguyen Thai Ngoc Duy @ 2007-09-29 5:32 UTC (permalink / raw)
To: Carl Worth; +Cc: git
In-Reply-To: <87ir5us82a.wl%cworth@cworth.org>
On 9/29/07, Carl Worth <cworth@cworth.org> wrote:
> I recently "ported" the introductory chapter of Bryan O'Sullivan's
> Distributed revision control with Mercurial[1] from mercurial to
> git. The result is here:
>
> A tour of git: the basics
> http://cworth.org/hgbook-git/tour/
Minor thing. On Gentoo you should do "emerge dev-util/git" instead of
"emerge git" because there is another program with the same name.
--
Duy
^ permalink raw reply
* [PATCH 1/3] Use parse_date_format() convenience function for converting a format string to an enum date_mode in revisions.c
From: Andy Parkins @ 2007-09-29 7:39 UTC (permalink / raw)
To: git
In-Reply-To: <7v1wcipsn9.fsf@gitster.siamese.dyndns.org>
parse_date_format() is passed a string that is compared against a
pre-defined list and converted to an enum date_format. The table is as
follows:
- "relative" => DATE_RELATIVE
- "iso8601" or "iso" => DATE_ISO8601
- "rfc2822" => DATE_RFC2822
- "short" => DATE_SHORT
- "local" => DATE_LOCAL
- "default" => DATE_NORMAL
In the event that none of these strings is found, the function die()s.
Then we use parse_date_format() in revisions.c to parse the --date
parameter. The --date parameter was previously handled in revisions.c
with a list of if(strcmp()) calls; now parse_date_format() is called
instead.
Signed-off-by: Andy Parkins <andyparkins@gmail.com>
---
cache.h | 1 +
date.c | 20 ++++++++++++++++++++
revision.c | 17 +----------------
3 files changed, 22 insertions(+), 16 deletions(-)
diff --git a/cache.h b/cache.h
index 8246500..5587f7e 100644
--- a/cache.h
+++ b/cache.h
@@ -432,6 +432,7 @@ const char *show_date(unsigned long time, int timezone, enum date_mode mode);
int parse_date(const char *date, char *buf, int bufsize);
void datestamp(char *buf, int bufsize);
unsigned long approxidate(const char *);
+enum date_mode parse_date_format(const char *format);
extern const char *git_author_info(int);
extern const char *git_committer_info(int);
diff --git a/date.c b/date.c
index 93bef6e..8f70500 100644
--- a/date.c
+++ b/date.c
@@ -584,6 +584,26 @@ int parse_date(const char *date, char *result, int maxlen)
return date_string(then, offset, result, maxlen);
}
+enum date_mode parse_date_format(const char *format)
+{
+ if (!strcmp(format, "relative"))
+ return DATE_RELATIVE;
+ else if (!strcmp(format, "iso8601") ||
+ !strcmp(format, "iso"))
+ return DATE_ISO8601;
+ else if (!strcmp(format, "rfc2822") ||
+ !strcmp(format, "rfc"))
+ return DATE_RFC2822;
+ else if (!strcmp(format, "short"))
+ return DATE_SHORT;
+ else if (!strcmp(format, "local"))
+ return DATE_LOCAL;
+ else if (!strcmp(format, "default"))
+ return DATE_NORMAL;
+ else
+ die("unknown date format %s", format);
+}
+
void datestamp(char *buf, int bufsize)
{
time_t now;
diff --git a/revision.c b/revision.c
index 33d092c..75cd0c6 100644
--- a/revision.c
+++ b/revision.c
@@ -1134,22 +1134,7 @@ int setup_revisions(int argc, const char **argv, struct rev_info *revs, const ch
continue;
}
if (!strncmp(arg, "--date=", 7)) {
- if (!strcmp(arg + 7, "relative"))
- revs->date_mode = DATE_RELATIVE;
- else if (!strcmp(arg + 7, "iso8601") ||
- !strcmp(arg + 7, "iso"))
- revs->date_mode = DATE_ISO8601;
- else if (!strcmp(arg + 7, "rfc2822") ||
- !strcmp(arg + 7, "rfc"))
- revs->date_mode = DATE_RFC2822;
- else if (!strcmp(arg + 7, "short"))
- revs->date_mode = DATE_SHORT;
- else if (!strcmp(arg + 7, "local"))
- revs->date_mode = DATE_LOCAL;
- else if (!strcmp(arg + 7, "default"))
- revs->date_mode = DATE_NORMAL;
- else
- die("unknown date format %s", arg);
+ revs->date_mode = parse_date_format(arg + 7);
continue;
}
if (!strcmp(arg, "--log-size")) {
--
1.5.3.rc5.11.g312e
^ permalink raw reply related
* [PATCH 2/3] Make for-each-ref allow atom names like "<name>:<something>"
From: Andy Parkins @ 2007-09-29 7:39 UTC (permalink / raw)
To: git
In-Reply-To: <7v1wcipsn9.fsf@gitster.siamese.dyndns.org>
In anticipation of supplying a per-field date format specifier, this
patch makes parse_atom() in builtin-for-each-ref.c allow atoms that have
a valid atom name (as determined by the valid_atom[] table) followed by
a colon, followed by an arbitrary string.
The arbitrary string is where the format for the atom will be specified.
Note, if different formats are specified for the same atom, multiple
entries will be made in the used_atoms table to allow them to be
distinguished by the grab_XXXX() functions.
Signed-off-by: Andy Parkins <andyparkins@gmail.com>
---
builtin-for-each-ref.c | 8 +++++++-
1 files changed, 7 insertions(+), 1 deletions(-)
diff --git a/builtin-for-each-ref.c b/builtin-for-each-ref.c
index 0afa1c5..3280516 100644
--- a/builtin-for-each-ref.c
+++ b/builtin-for-each-ref.c
@@ -106,7 +106,13 @@ static int parse_atom(const char *atom, const char *ep)
/* Is the atom a valid one? */
for (i = 0; i < ARRAY_SIZE(valid_atom); i++) {
int len = strlen(valid_atom[i].name);
- if (len == ep - sp && !memcmp(valid_atom[i].name, sp, len))
+ /* If the atom name has a colon, strip it and everything after
+ * it off - it specifies the format for this entry, and
+ * shouldn't be used for checking against the valid_atom table */
+ const char *formatp = strrchr(sp, ':' );
+ if (formatp == NULL )
+ formatp = ep;
+ if (len == formatp - sp && !memcmp(valid_atom[i].name, sp, len))
break;
}
--
1.5.3.rc5.11.g312e
^ permalink raw reply related
* [PATCH 3/3] Make for-each-ref's grab_date() support per-atom formatting
From: Andy Parkins @ 2007-09-29 7:39 UTC (permalink / raw)
To: git
In-Reply-To: <7v1wcipsn9.fsf@gitster.siamese.dyndns.org>
grab_date() gets an extra parameter - atomname; this extra parameter is
checked to see if it has a ":<format>" extra component in it, and if so
that "<format>" string is passed to parse_date_format() to produce an
enum date_mode value which is then further passed to show_date().
In short it allows the user of git-for-each-ref to do things like this:
$ git-for-each-ref --format='%(taggerdate:default)' refs/tags/v1.5.2
Sun May 20 00:30:42 2007 -0700
$ git-for-each-ref --format='%(taggerdate:relative)' refs/tags/v1.5.2
4 months ago
$ git-for-each-ref --format='%(taggerdate:short)' refs/tags/v1.5.2
2007-05-20
$ git-for-each-ref --format='%(taggerdate:local)' refs/tags/v1.5.2
Sun May 20 08:30:42 2007
$ git-for-each-ref --format='%(taggerdate:iso8601)' refs/tags/v1.5.2
2007-05-20 00:30:42 -0700
$ git-for-each-ref --format='%(taggerdate:rfc2822)' refs/tags/v1.5.2
Sun, 20 May 2007 00:30:42 -0700
The default, when no ":<format>" is specified is ":default", leaving the
existing behaviour unchanged.
Signed-off-by: Andy Parkins <andyparkins@gmail.com>
---
Documentation/git-for-each-ref.txt | 5 +++++
builtin-for-each-ref.c | 26 +++++++++++++++++++-------
2 files changed, 24 insertions(+), 7 deletions(-)
diff --git a/Documentation/git-for-each-ref.txt b/Documentation/git-for-each-ref.txt
index 6df8e85..f1f90cc 100644
--- a/Documentation/git-for-each-ref.txt
+++ b/Documentation/git-for-each-ref.txt
@@ -100,6 +100,11 @@ In any case, a field name that refers to a field inapplicable to
the object referred by the ref does not cause an error. It
returns an empty string instead.
+As a special case for the date-type fields, you may specify a format for
+the date by adding one of `:default`, `:relative`, `:short`, `:local`,
+`:iso8601` or `:rfc2822` to the end of the fieldname; e.g.
+`%(taggerdate:relative)`.
+
EXAMPLES
--------
diff --git a/builtin-for-each-ref.c b/builtin-for-each-ref.c
index 3280516..2ca4fc6 100644
--- a/builtin-for-each-ref.c
+++ b/builtin-for-each-ref.c
@@ -353,12 +353,24 @@ static const char *copy_email(const char *buf)
return line;
}
-static void grab_date(const char *buf, struct atom_value *v)
+static void grab_date(const char *buf, struct atom_value *v, const char *atomname)
{
const char *eoemail = strstr(buf, "> ");
char *zone;
unsigned long timestamp;
long tz;
+ enum date_mode date_mode = DATE_NORMAL;
+ const char *formatp;
+
+ /* We got here because atomname ends in "date" or "date<something>",
+ * it's not possible that <something> is not ":<format>" because
+ * parse_atom() wouldn't have allowed it, so we can assume that no
+ * ":" means no format is specified, use the default */
+ formatp = strrchr( atomname, ':' );
+ if (formatp != NULL) {
+ formatp++;
+ date_mode = parse_date_format(formatp);
+ }
if (!eoemail)
goto bad;
@@ -368,7 +380,7 @@ static void grab_date(const char *buf, struct atom_value *v)
tz = strtol(zone, NULL, 10);
if ((tz == LONG_MIN || tz == LONG_MAX) && errno == ERANGE)
goto bad;
- v->s = xstrdup(show_date(timestamp, tz, 0));
+ v->s = xstrdup(show_date(timestamp, tz, date_mode));
v->ul = timestamp;
return;
bad:
@@ -395,7 +407,7 @@ static void grab_person(const char *who, struct atom_value *val, int deref, stru
if (name[wholen] != 0 &&
strcmp(name + wholen, "name") &&
strcmp(name + wholen, "email") &&
- strcmp(name + wholen, "date"))
+ prefixcmp(name + wholen, "date"))
continue;
if (!wholine)
wholine = find_wholine(who, wholen, buf, sz);
@@ -407,8 +419,8 @@ static void grab_person(const char *who, struct atom_value *val, int deref, stru
v->s = copy_name(wholine);
else if (!strcmp(name + wholen, "email"))
v->s = copy_email(wholine);
- else if (!strcmp(name + wholen, "date"))
- grab_date(wholine, v);
+ else if (!prefixcmp(name + wholen, "date"))
+ grab_date(wholine, v, name);
}
/* For a tag or a commit object, if "creator" or "creatordate" is
@@ -428,8 +440,8 @@ static void grab_person(const char *who, struct atom_value *val, int deref, stru
if (deref)
name++;
- if (!strcmp(name, "creatordate"))
- grab_date(wholine, v);
+ if (!prefixcmp(name, "creatordate"))
+ grab_date(wholine, v, name);
else if (!strcmp(name, "creator"))
v->s = copy_line(wholine);
}
--
1.5.3.rc5.11.g312e
^ permalink raw reply related
* Re: A tour of git: the basics (and notes on some unfriendly messages)
From: Steffen Prohaska @ 2007-09-29 7:44 UTC (permalink / raw)
To: Johannes Schindelin; +Cc: Shawn O. Pearce, Carl Worth, git
In-Reply-To: <Pine.LNX.4.64.0709290144310.28395@racer.site>
On Sep 29, 2007, at 2:49 AM, Johannes Schindelin wrote:
>
> On Fri, 28 Sep 2007, Shawn O. Pearce wrote:
>
>> On Cygwin we have man, so `git help init` (or `git init --help`) work
>> just fine to display the manual entry. No idea about the MSYS port.
>
> We open the html pages. That is, we don't yet, since we do not
> generate
> the html pages just yet; asciidoc is a Python program, and Python
> is not
> available as an MSys program as far as I know (and asciidoc insists on
> finding files in a Unix-like file structure, so we _do_ need an MSys
> Python).
>
I propose to clone the html pages from git.git's html branch and
include them in the installer. I continue to believe that this is
the simplest and fastest solution for providing html pages.
I'll provide a patch (hopefully next week).
Steffen
^ permalink raw reply
* Re: Use of strbuf.buf when strbuf.len == 0
From: Pierre Habouzit @ 2007-09-29 7:48 UTC (permalink / raw)
To: Linus Torvalds; +Cc: Junio C Hamano, git
In-Reply-To: <alpine.LFD.0.999.0709281746500.3579@woody.linux-foundation.org>
[-- Attachment #1: Type: text/plain, Size: 3118 bytes --]
On Sat, Sep 29, 2007 at 12:51:36AM +0000, Linus Torvalds wrote:
>
>
> On Thu, 27 Sep 2007, Pierre Habouzit wrote:
> >
> > I can see a way, that would need special proof-reading of the strbuf
> > module, but should not harm its users, that would be to change
> > STRBUF_INIT to work this way:
> >
> > { .buf = "", .len = 0, .alloc = 0 }
>
> I'd like to pipe up a bit here..
>
> I think the above is a good fix for the current problem of wanting to
> always be able to use "sb->buf", but I thinkit actually has the potential
> to fix another issue entirely.
>
> Namely strbuf's that are initialized from various static strings and/or
> strings not directly allocated with malloc().
>
> That's not necessarily something really unusual. Wanting to initialize a
> string with a fixed constant value is a common problem.
>
> And wouldn't it be nice if you could actually do that, with
>
> { .buf = "static initializer", .len = 18, .alloc = 0 }
>
> and have all the strbuf routines that modify the initializer (including
> making it shorter!) notice that the allocation is too short, and create a
> new allocation?
We could probably do that. The places to change to make this work are
seldom:
* strbuf_grow to emulate a realloc (and copy the buffer into the new
malloc()ed one),
* strbuf_release assumes that ->alloc == 0 means _init isn't
necessary, it would be now,
* strbuf_setlen should not have the assert anymore (though I'm not
sure this assert still makes sense with the new initializer).
and that's it.
But we cannot initialize a strbuf with an immediate string because all
the strbuf APIs suppose that the strbuf buffer are writeable (and IMHO
it's pointless to use a strbuf for reading purposes). Other point, I've
made many readings of the code searching for specific patterns of code,
to replace with strbuf's, and I've never seen places (I do not say those
don't exists though) that would directly benefit from that.
> Hmm?
So I'd say I'll keep the idea in mind, because it's tasteful and could
help, though I'd prefer Junio to review that patch, and then later add
this new semantics if the need arises.
The sole thing that may be worth investigating would look like:
char internal_buf[PATH_MAX]; /* should be damn long enough */
struct strbuf buf;
strbuf_init_static(&buf, internal_buf, sizeof(internal_buf);
/* hack with the strbuf API */
strbuf_release(&buf); /* do release memory, in case we went over
PATH_MAX octets */
because it could save some allocations _and_ be safe at the same time.
But I don't really like it, when allocation is critical in git, it's
rarely in functions where there is an obvious size limit for the
problem, and avoiding allocations can be done using static strbufs
(fast-import.c does that in many places).
--
·O· Pierre Habouzit
··O madcoder@debian.org
OOO http://www.madism.org
[-- Attachment #2: Type: application/pgp-signature, Size: 189 bytes --]
^ permalink raw reply
* Re: [PATCH 4/4] Make for-each-ref's grab_date() support per-atom formatting
From: Junio C Hamano @ 2007-09-29 8:17 UTC (permalink / raw)
To: Andy Parkins; +Cc: git
In-Reply-To: <200709281517.45133.andyparkins@gmail.com>
I squashed 1+2 together so there is no need to resend. It would
be nice to see a few tests in the test suite though.
^ permalink raw reply
* Re: A tour of git: the basics (and notes on some unfriendly messages)
From: Pierre Habouzit @ 2007-09-29 9:01 UTC (permalink / raw)
To: Shawn O. Pearce; +Cc: Carl Worth, git
In-Reply-To: <20070929000056.GZ3099@spearce.org>
[-- Attachment #1: Type: text/plain, Size: 2015 bytes --]
On Sat, Sep 29, 2007 at 12:00:56AM +0000, Shawn O. Pearce wrote:
> The C based git-fetch made the http protocol almost totally silent.
> (No more got/walk messages.) But that's actually also bad as it
> now doesn't even let you know its transferring anything at all.
>
> There are serious issues here about getting the user the progress
> they really want. The last item ("When will this be done?") is
> actually not possible to determine under either the native git
> protocol or HTTP/FTP. We have no idea up front how much data must
> be transferred. In the native git case we do know how many objects,
> but we don't know how many bytes that will be. It could be under
> a kilobyte in one project. That same object count for a different
> set of objects fetch could be 500M. Radically different transfer
> times would be required.
I'm not sure you need the ETA thing. I've used bzr only a couple of
time, I don't think it shows any kind of ETA, but I think I remember sth
like:
Stage 3/4
[==========================> ] [43%]
And that's all is needed. It's sober, and informative enough I think.
Many git commands output are still messy and indeed, having them in C
should help in that regard. The usual culprit are I think:
* git fetch/clone/pull/.. ;
* git push ;
* git repack/gc/... ;
* git merge (even with the merge.verbosity set to the minimum it's
still not very readable and confusing).
I do believe that the quite verbose output git commands sometimes have
is quite confusing, and let the user think it's messy. I believe that
porcelains should be more silent, it's OK for the plumbing to spit
progress messages and so on, because people using the plumbing are able
to understand those, but porcelains should not.
--
·O· Pierre Habouzit
··O madcoder@debian.org
OOO http://www.madism.org
[-- Attachment #2: Type: application/pgp-signature, Size: 189 bytes --]
^ permalink raw reply
* Re: [PATCH] git-bundle: fix commandline examples in the manpage
From: Junio C Hamano @ 2007-09-29 9:20 UTC (permalink / raw)
To: Miklos Vajna; +Cc: git
In-Reply-To: <1190849699-11265-1-git-send-email-vmiklos@frugalware.org>
Thanks.
^ permalink raw reply
* Re: git-mergetool
From: Junio C Hamano @ 2007-09-29 9:27 UTC (permalink / raw)
To: Mattias Ulbrich; +Cc: git
In-Reply-To: <200709281056.15844.mulbrich@ira.uka.de>
Thanks.
^ permalink raw reply
* [PATCH] gitk: add check for required tcl version >= 8.4
From: Junio C Hamano @ 2007-09-29 9:32 UTC (permalink / raw)
To: paulus; +Cc: git, Steffen Prohaska
From: Steffen Prohaska <prohaska@zib.de>
Date: Fri, 28 Sep 2007 22:57:22 +0200
gitk requires tcl version >= 8.4 to work flawlessly. So let's
check the tcl version and quit if it's too low.
Signed-off-by: Steffen Prohaska <prohaska@zib.de>
---
* I do not have a ready access to older tcl/tk myself, so I
cannot judge if this is sensible or not. Just forwarding in
case you missed it.
gitk | 5 +++++
1 files changed, 5 insertions(+), 0 deletions(-)
diff --git a/gitk b/gitk
index 300fdce..6ea6489 100755
--- a/gitk
+++ b/gitk
@@ -7,6 +7,11 @@ exec wish "$0" -- "$@"
# and distributed under the terms of the GNU General Public Licence,
# either version 2, or (at your option) any later version.
+if {[info tclversion] < 8.4} {
+ puts stderr "Sorry, gitk requires tcl version >= 8.4."
+ exit 1
+}
+
proc gitdir {} {
global env
if {[info exists env(GIT_DIR)]} {
--
1.5.3.2.111.g5166
^ permalink raw reply related
* [PATCH 1/4] git.el: Preserve file marks when doing a full refresh.
From: Alexandre Julliard @ 2007-09-29 9:58 UTC (permalink / raw)
To: git
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
---
contrib/emacs/git.el | 40 ++++++++++++++++++++++++++++------------
1 files changed, 28 insertions(+), 12 deletions(-)
diff --git a/contrib/emacs/git.el b/contrib/emacs/git.el
index 2d77fd4..7b4a0d3 100644
--- a/contrib/emacs/git.el
+++ b/contrib/emacs/git.el
@@ -494,24 +494,31 @@ and returns the process output as a string."
(setf (git-fileinfo->orig-name info) nil)
(setf (git-fileinfo->needs-refresh info) t))))
-(defun git-set-filenames-state (status files state)
- "Set the state of a list of named files."
+(defun git-status-filenames-map (status func files &rest args)
+ "Apply FUNC to the status files names in the FILES list."
(when files
(setq files (sort files #'string-lessp))
(let ((file (pop files))
(node (ewoc-nth status 0)))
(while (and file node)
(let ((info (ewoc-data node)))
- (cond ((string-lessp (git-fileinfo->name info) file)
- (setq node (ewoc-next status node)))
- ((string-equal (git-fileinfo->name info) file)
- (unless (eq (git-fileinfo->state info) state)
- (setf (git-fileinfo->state info) state)
- (setf (git-fileinfo->rename-state info) nil)
- (setf (git-fileinfo->orig-name info) nil)
- (setf (git-fileinfo->needs-refresh info) t))
- (setq file (pop files)))
- (t (setq file (pop files)))))))
+ (if (string-lessp (git-fileinfo->name info) file)
+ (setq node (ewoc-next status node))
+ (if (string-equal (git-fileinfo->name info) file)
+ (apply func info args))
+ (setq file (pop files))))))))
+
+(defun git-set-filenames-state (status files state)
+ "Set the state of a list of named files."
+ (when files
+ (git-status-filenames-map status
+ (lambda (info state)
+ (unless (eq (git-fileinfo->state info) state)
+ (setf (git-fileinfo->state info) state)
+ (setf (git-fileinfo->rename-state info) nil)
+ (setf (git-fileinfo->orig-name info) nil)
+ (setf (git-fileinfo->needs-refresh info) t)))
+ files state)
(unless state ;; delete files whose state has been set to nil
(ewoc-filter status (lambda (info) (git-fileinfo->state info))))))
@@ -1197,11 +1204,20 @@ Return the list of files that haven't been handled."
(interactive)
(let* ((status git-status)
(pos (ewoc-locate status))
+ (marked-files (git-get-filenames (ewoc-collect status (lambda (info) (git-fileinfo->marked info)))))
(cur-name (and pos (git-fileinfo->name (ewoc-data pos)))))
(unless status (error "Not in git-status buffer."))
(git-run-command nil nil "update-index" "--refresh")
(git-clear-status status)
(git-update-status-files nil)
+ ; restore file marks
+ (when marked-files
+ (git-status-filenames-map status
+ (lambda (info)
+ (setf (git-fileinfo->marked info) t)
+ (setf (git-fileinfo->needs-refresh info) t))
+ marked-files)
+ (git-refresh-files))
; move point to the current file name if any
(let ((node (and cur-name (git-find-status-file status cur-name))))
(when node (ewoc-goto-node status node)))))
--
1.5.3.2.121.gf7223
--
Alexandre Julliard
julliard@winehq.org
^ permalink raw reply related
* [PATCH 2/4] git.el: Do not print a status message on every git command.
From: Alexandre Julliard @ 2007-09-29 9:58 UTC (permalink / raw)
To: git
Instead print a single message around sequences of commands that can
potentially take some time.
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
---
contrib/emacs/git.el | 70 +++++++++++++++++++++++++++++--------------------
1 files changed, 41 insertions(+), 29 deletions(-)
diff --git a/contrib/emacs/git.el b/contrib/emacs/git.el
index 7b4a0d3..ec2e699 100644
--- a/contrib/emacs/git.el
+++ b/contrib/emacs/git.el
@@ -220,22 +220,15 @@ and returns the process output as a string."
(message "Running git %s...done" (car args))
buffer))
-(defun git-run-command (buffer env &rest args)
- (message "Running git %s..." (car args))
- (apply #'git-call-process-env buffer env args)
- (message "Running git %s...done" (car args)))
-
(defun git-run-command-region (buffer start end env &rest args)
"Run a git command with specified buffer region as input."
- (message "Running git %s..." (car args))
(unless (eq 0 (if env
(git-run-process-region
buffer start end "env"
(append (git-get-env-strings env) (list "git") args))
(git-run-process-region
buffer start end "git" args)))
- (error "Failed to run \"git %s\":\n%s" (mapconcat (lambda (x) x) args " ") (buffer-string)))
- (message "Running git %s...done" (car args)))
+ (error "Failed to run \"git %s\":\n%s" (mapconcat (lambda (x) x) args " ") (buffer-string))))
(defun git-run-hook (hook env &rest args)
"Run a git hook and display its output if any."
@@ -312,6 +305,13 @@ and returns the process output as a string."
"\"")
name))
+(defun git-success-message (text files)
+ "Print a success message after having handled FILES."
+ (let ((n (length files)))
+ (if (equal n 1)
+ (message "%s %s" text (car files))
+ (message "%s %d files" text n))))
+
(defun git-get-top-dir (dir)
"Retrieve the top-level directory of a git tree."
(let ((cdup (with-output-to-string
@@ -338,7 +338,7 @@ and returns the process output as a string."
(sort-lines nil (point-min) (point-max))
(save-buffer))
(when created
- (git-run-command nil nil "update-index" "--add" "--" (file-relative-name ignore-name)))
+ (git-call-process-env nil nil "update-index" "--add" "--" (file-relative-name ignore-name)))
(git-update-status-files (list (file-relative-name ignore-name)) 'unknown)))
; propertize definition for XEmacs, stolen from erc-compat
@@ -606,7 +606,7 @@ and returns the process output as a string."
Return the list of files that haven't been handled."
(let (infolist)
(with-temp-buffer
- (apply #'git-run-command t nil "diff-index" "-z" "-M" "HEAD" "--" files)
+ (apply #'git-call-process-env t nil "diff-index" "-z" "-M" "HEAD" "--" files)
(goto-char (point-min))
(while (re-search-forward
":\\([0-7]\\{6\\}\\) \\([0-7]\\{6\\}\\) [0-9a-f]\\{40\\} [0-9a-f]\\{40\\} \\(\\([ADMU]\\)\0\\([^\0]+\\)\\|\\([CR]\\)[0-9]*\0\\([^\0]+\\)\0\\([^\0]+\\)\\)\0"
@@ -639,7 +639,7 @@ Return the list of files that haven't been handled."
Return the list of files that haven't been handled."
(let (infolist)
(with-temp-buffer
- (apply #'git-run-command t nil "ls-files" "-z" (append options (list "--") files))
+ (apply #'git-call-process-env t nil "ls-files" "-z" (append options (list "--") files))
(goto-char (point-min))
(while (re-search-forward "\\([^\0]*\\)\0" nil t 1)
(let ((name (match-string 1)))
@@ -651,7 +651,7 @@ Return the list of files that haven't been handled."
(defun git-run-ls-unmerged (status files)
"Run git-ls-files -u on FILES and parse the results into STATUS."
(with-temp-buffer
- (apply #'git-run-command t nil "ls-files" "-z" "-u" "--" files)
+ (apply #'git-call-process-env t nil "ls-files" "-z" "-u" "--" files)
(goto-char (point-min))
(let (unmerged-files)
(while (re-search-forward "[0-7]\\{6\\} [0-9a-f]\\{40\\} [123]\t\\([^\0]+\\)\0" nil t)
@@ -754,11 +754,11 @@ Return the list of files that haven't been handled."
('deleted (push info deleted))
('modified (push info modified))))
(when added
- (apply #'git-run-command nil env "update-index" "--add" "--" (git-get-filenames added)))
+ (apply #'git-call-process-env nil env "update-index" "--add" "--" (git-get-filenames added)))
(when deleted
- (apply #'git-run-command nil env "update-index" "--remove" "--" (git-get-filenames deleted)))
+ (apply #'git-call-process-env nil env "update-index" "--remove" "--" (git-get-filenames deleted)))
(when modified
- (apply #'git-run-command nil env "update-index" "--" (git-get-filenames modified)))))
+ (apply #'git-call-process-env nil env "update-index" "--" (git-get-filenames modified)))))
(defun git-run-pre-commit-hook ()
"Run the pre-commit hook if any."
@@ -790,6 +790,7 @@ Return the list of files that haven't been handled."
head-tree (git-rev-parse "HEAD^{tree}")))
(if files
(progn
+ (message "Running git commit...")
(git-read-tree head-tree index-file)
(git-update-index nil files) ;update both the default index
(git-update-index index-file files) ;and the temporary one
@@ -801,7 +802,7 @@ Return the list of files that haven't been handled."
(condition-case nil (delete-file ".git/MERGE_MSG") (error nil))
(with-current-buffer buffer (erase-buffer))
(git-set-files-state files 'uptodate)
- (git-run-command nil nil "rerere")
+ (git-call-process-env nil nil "rerere")
(git-refresh-files)
(git-refresh-ewoc-hf git-status)
(message "Committed %s." commit)
@@ -912,8 +913,9 @@ Return the list of files that haven't been handled."
(let ((files (git-get-filenames (git-marked-files-state 'unknown 'ignored))))
(unless files
(push (file-relative-name (read-file-name "File to add: " nil nil t)) files))
- (apply #'git-run-command nil nil "update-index" "--add" "--" files)
- (git-update-status-files files 'uptodate)))
+ (apply #'git-call-process-env nil nil "update-index" "--add" "--" files)
+ (git-update-status-files files 'uptodate)
+ (git-success-message "Added" files)))
(defun git-ignore-file ()
"Add marked file(s) to the ignore list."
@@ -922,7 +924,8 @@ Return the list of files that haven't been handled."
(unless files
(push (file-relative-name (read-file-name "File to ignore: " nil nil t)) files))
(dolist (f files) (git-append-to-ignore f))
- (git-update-status-files files 'ignored)))
+ (git-update-status-files files 'ignored)
+ (git-success-message "Ignored" files)))
(defun git-remove-file ()
"Remove the marked file(s)."
@@ -935,8 +938,9 @@ Return the list of files that haven't been handled."
(progn
(dolist (name files)
(when (file-exists-p name) (delete-file name)))
- (apply #'git-run-command nil nil "update-index" "--remove" "--" files)
- (git-update-status-files files nil))
+ (apply #'git-call-process-env nil nil "update-index" "--remove" "--" files)
+ (git-update-status-files files nil)
+ (git-success-message "Removed" files))
(message "Aborting"))))
(defun git-revert-file ()
@@ -954,18 +958,20 @@ Return the list of files that haven't been handled."
('unmerged (push (git-fileinfo->name info) modified))
('modified (push (git-fileinfo->name info) modified))))
(when added
- (apply #'git-run-command nil nil "update-index" "--force-remove" "--" added))
+ (apply #'git-call-process-env nil nil "update-index" "--force-remove" "--" added))
(when modified
- (apply #'git-run-command nil nil "checkout" "HEAD" modified))
- (git-update-status-files (append added modified) 'uptodate))))
+ (apply #'git-call-process-env nil nil "checkout" "HEAD" modified))
+ (git-update-status-files (append added modified) 'uptodate)
+ (git-success-message "Reverted" files))))
(defun git-resolve-file ()
"Resolve conflicts in marked file(s)."
(interactive)
(let ((files (git-get-filenames (git-marked-files-state 'unmerged))))
(when files
- (apply #'git-run-command nil nil "update-index" "--" files)
- (git-update-status-files files 'uptodate))))
+ (apply #'git-call-process-env nil nil "update-index" "--" files)
+ (git-update-status-files files 'uptodate)
+ (git-success-message "Resolved" files))))
(defun git-remove-handled ()
"Remove handled files from the status list."
@@ -992,9 +998,11 @@ Return the list of files that haven't been handled."
(interactive)
(if (setq git-show-ignored (not git-show-ignored))
(progn
+ (message "Inserting ignored files...")
(git-run-ls-files-with-excludes git-status nil 'ignored "-o" "-i")
(git-refresh-files)
- (git-refresh-ewoc-hf git-status))
+ (git-refresh-ewoc-hf git-status)
+ (message "Inserting ignored files...done"))
(git-remove-handled)))
(defun git-toggle-show-unknown ()
@@ -1002,9 +1010,11 @@ Return the list of files that haven't been handled."
(interactive)
(if (setq git-show-unknown (not git-show-unknown))
(progn
+ (message "Inserting unknown files...")
(git-run-ls-files-with-excludes git-status nil 'unknown "-o")
(git-refresh-files)
- (git-refresh-ewoc-hf git-status))
+ (git-refresh-ewoc-hf git-status)
+ (message "Inserting unknown files...done"))
(git-remove-handled)))
(defun git-setup-diff-buffer (buffer)
@@ -1207,7 +1217,8 @@ Return the list of files that haven't been handled."
(marked-files (git-get-filenames (ewoc-collect status (lambda (info) (git-fileinfo->marked info)))))
(cur-name (and pos (git-fileinfo->name (ewoc-data pos)))))
(unless status (error "Not in git-status buffer."))
- (git-run-command nil nil "update-index" "--refresh")
+ (message "Refreshing git status...")
+ (git-call-process-env nil nil "update-index" "--refresh")
(git-clear-status status)
(git-update-status-files nil)
; restore file marks
@@ -1219,6 +1230,7 @@ Return the list of files that haven't been handled."
marked-files)
(git-refresh-files))
; move point to the current file name if any
+ (message "Refreshing git status...done")
(let ((node (and cur-name (git-find-status-file status cur-name))))
(when node (ewoc-goto-node status node)))))
--
1.5.3.2.121.gf7223
--
Alexandre Julliard
julliard@winehq.org
^ permalink raw reply related
* [PATCH 3/4] git.el: Update a file status in the git buffer upon save.
From: Alexandre Julliard @ 2007-09-29 9:59 UTC (permalink / raw)
To: git
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
---
contrib/emacs/git.el | 18 ++++++++++++++++--
1 files changed, 16 insertions(+), 2 deletions(-)
diff --git a/contrib/emacs/git.el b/contrib/emacs/git.el
index ec2e699..c2a1c3d 100644
--- a/contrib/emacs/git.el
+++ b/contrib/emacs/git.el
@@ -36,7 +36,6 @@
;; TODO
;; - portability to XEmacs
;; - better handling of subprocess errors
-;; - hook into file save (after-save-hook)
;; - diff against other branch
;; - renaming files from the status buffer
;; - creating tags
@@ -1352,9 +1351,24 @@ Commands:
(cd dir)
(git-status-mode)
(git-refresh-status)
- (goto-char (point-min)))
+ (goto-char (point-min))
+ (add-hook 'after-save-hook 'git-update-saved-file))
(message "%s is not a git working tree." dir)))
+(defun git-update-saved-file ()
+ "Update the corresponding git-status buffer when a file is saved.
+Meant to be used in `after-save-hook'."
+ (let* ((file (expand-file-name buffer-file-name))
+ (dir (condition-case nil (git-get-top-dir (file-name-directory file))))
+ (buffer (and dir (git-find-status-buffer dir))))
+ (when buffer
+ (with-current-buffer buffer
+ (let ((filename (file-relative-name file dir)))
+ ; skip files located inside the .git directory
+ (unless (string-match "^\\.git/" filename)
+ (git-call-process-env nil nil "add" "--refresh" "--" filename)
+ (git-update-status-files (list filename) 'uptodate)))))))
+
(defun git-help ()
"Display help for Git mode."
(interactive)
--
1.5.3.2.121.gf7223
--
Alexandre Julliard
julliard@winehq.org
^ permalink raw reply related
* [PATCH 4/4] git.el: Reset the permission flags when changing a file state.
From: Alexandre Julliard @ 2007-09-29 9:59 UTC (permalink / raw)
To: git
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
---
contrib/emacs/git.el | 28 +++++++++++-----------------
1 files changed, 11 insertions(+), 17 deletions(-)
diff --git a/contrib/emacs/git.el b/contrib/emacs/git.el
index c2a1c3d..4286d16 100644
--- a/contrib/emacs/git.el
+++ b/contrib/emacs/git.el
@@ -484,14 +484,15 @@ and returns the process output as a string."
"Remove everything from the status list."
(ewoc-filter status (lambda (info) nil)))
-(defun git-set-files-state (files state)
- "Set the state of a list of files."
- (dolist (info files)
- (unless (eq (git-fileinfo->state info) state)
- (setf (git-fileinfo->state info) state)
- (setf (git-fileinfo->rename-state info) nil)
- (setf (git-fileinfo->orig-name info) nil)
- (setf (git-fileinfo->needs-refresh info) t))))
+(defun git-set-fileinfo-state (info state)
+ "Set the state of a file info."
+ (unless (eq (git-fileinfo->state info) state)
+ (setf (git-fileinfo->state info) state
+ (git-fileinfo->old-perm info) 0
+ (git-fileinfo->new-perm info) 0
+ (git-fileinfo->rename-state info) nil
+ (git-fileinfo->orig-name info) nil
+ (git-fileinfo->needs-refresh info) t)))
(defun git-status-filenames-map (status func files &rest args)
"Apply FUNC to the status files names in the FILES list."
@@ -510,14 +511,7 @@ and returns the process output as a string."
(defun git-set-filenames-state (status files state)
"Set the state of a list of named files."
(when files
- (git-status-filenames-map status
- (lambda (info state)
- (unless (eq (git-fileinfo->state info) state)
- (setf (git-fileinfo->state info) state)
- (setf (git-fileinfo->rename-state info) nil)
- (setf (git-fileinfo->orig-name info) nil)
- (setf (git-fileinfo->needs-refresh info) t)))
- files state)
+ (git-status-filenames-map status #'git-set-fileinfo-state files state)
(unless state ;; delete files whose state has been set to nil
(ewoc-filter status (lambda (info) (git-fileinfo->state info))))))
@@ -800,7 +794,7 @@ Return the list of files that haven't been handled."
(condition-case nil (delete-file ".git/MERGE_HEAD") (error nil))
(condition-case nil (delete-file ".git/MERGE_MSG") (error nil))
(with-current-buffer buffer (erase-buffer))
- (git-set-files-state files 'uptodate)
+ (dolist (info files) (git-set-fileinfo-state info 'uptodate))
(git-call-process-env nil nil "rerere")
(git-refresh-files)
(git-refresh-ewoc-hf git-status)
--
1.5.3.2.121.gf7223
--
Alexandre Julliard
julliard@winehq.org
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox