threads / patch / 574

patchStop git-rev-list at sha1 match

Subject: [PATCH] Stop git-rev-list at sha1 match

## tl;dr

13 messages between May 11, 2005 and May 13, 2005. Diffs are folded; open one to read it.

replies: 12people: 3as markdown or json

Thomas Gleixner· May 11, 2005, 19:24 UTC · lore

The patch adds an option to stop the output of git-rev-list on a sha1 match.

Signed-Off: Thomas Gleixner <tglx@linutronix.de>
Show changes to rev-list.c +10 −2
--- a/rev-list.c
+++ b/rev-list.c
@@ -7,6 +7,8 @@ int main(int argc, char **argv)
 	struct commit_list *list = NULL;
 	struct commit *commit;
 	char *commit_arg = NULL;
+	char *sha1hex;
+	char *to_sha1 = NULL;
 	int i;
 	unsigned long max_age = -1;
 	unsigned long min_age = -1;
@@ -21,6 +23,8 @@ int main(int argc, char **argv)
 			max_age = atoi(arg + 10);
 		} else if (!strncmp(arg, "--min-age=", 10)) {
 			min_age = atoi(arg + 10);
+		} else if (!strncmp(arg, "--to_sha1=", 10)) {
+			to_sha1 = arg + 10;
 		} else {
 			commit_arg = arg;
 		}
@@ -30,7 +34,8 @@ int main(int argc, char **argv)
 		usage("usage: rev-list [OPTION] commit-id\n"
 		      "  --max-count=nr\n"
 		      "  --max-age=epoch\n"
-		      "  --min-age=epoch\n");
+		      "  --min-age=epoch\n"
+		      "  --to-sha1=sha1\n");
 
 	commit = lookup_commit(sha1);
 	if (!commit || parse_commit(commit) < 0)
@@ -46,7 +51,10 @@ int main(int argc, char **argv)
 			break;
 		if (max_count != -1 && !max_count--)
 			break;
-		printf("%s\n", sha1_to_hex(commit->object.sha1));
+		sha1hex = sha1_to_hex(commit->object.sha1);
+		if (to_sha1 != NULL && strcmp(to_sha1, sha1hex) == 0)
+			break;
+		printf("%s\n", sha1hex);
 	} while (list);
 	return 0;
 }
Junio C Hamano· May 11, 2005, 20:03 UTC · re: Thomas Gleixner · lore

Re: [PATCH] Stop git-rev-list at sha1 match

>>>>> "TG" == Thomas Gleixner <tglx@linutronix.de> writes:

TG> The patch adds an option to stop the output of git-rev-list TG> on a sha1 match.

One minor nit and two suggestions.  Otherwise looks good.
TG> Signed-Off: Thomas Gleixner <tglx@linutronix.de>

Nit. Please spell it "Signed-off-by: ". I have seen some people spell "off" with capital "O" so I guess it is also permitted.

TG> } else if (!strncmp(arg, "--min-age=", 10)) { TG> min_age = atoi(arg + 10); TG> + } else if (!strncmp(arg, "--to_sha1=", 10)) { TG> + to_sha1 = arg + 10;

Suggestion. How about renaming "--to_sha1" to "--since"? If you do not like "--since", then "--stop-at" would also be good.

The point being that I do not think we need to emphasize that the 40-character object IDs are produced by an algorithm that happens to use SHA1 hash in one of the steps of the computation. That is just an implementation detail and irrelevant to the user. What you are accepting here is really the object ID of the commit object.

At the very least, "--to-sha1" (hyphen not underscore) for consistency, please.

TG> + sha1hex = sha1_to_hex(commit->object.sha1); TG> + if (to_sha1 != NULL && strcmp(to_sha1, sha1hex) == 0) TG> + break;

Suggestion. Instead of running sha1_to_hex on the SHA1 of the commit and comparing strings for every commit you encounter, how about keeping 20-byte raw SHA1 of to_sha1 and doing memcmp of 20-byte? That way you would also detect malformed --to-sha1 parameter when you do the initial conversion upon argument parsing. Also the argument parsing using get_sha1() would give you an added benefit of using mnemonics (tag and heads).

What do you think about this revision?

---------------------------------------- [PATCH] Introduce "rev-list --stop-at=<commit>".

Additional option, --stop-at=<commit>, is introduced. The rev-list output stops after showing the named commit.

This is based on Thoms Gleixner's patch but slightly reworked.
Signed-off-by: Junio C Hamano <junkio@cox.net> 
---
Show changes to rev-list.c +16 −4
--- a/rev-list.c
+++ b/rev-list.c
@@ -1,12 +1,21 @@
 #include "cache.h"
 #include "commit.h"
 
+static const char *rev_list_usage = 
+"usage: rev-list [OPTION] commit-id\n"
+"  --max-count=nr\n"
+"  --max-age=epoch\n"
+"  --min-age=epoch\n"
+"  --stop-at=commit\n";
+
 int main(int argc, char **argv)
 {
 	unsigned char sha1[20];
 	struct commit_list *list = NULL;
 	struct commit *commit;
 	char *commit_arg = NULL;
+	unsigned char stop_at[20];
+	int has_stop_at = 0;
 	int i;
 	unsigned long max_age = -1;
 	unsigned long min_age = -1;
@@ -21,16 +30,17 @@ int main(int argc, char **argv)
 			max_age = atoi(arg + 10);
 		} else if (!strncmp(arg, "--min-age=", 10)) {
 			min_age = atoi(arg + 10);
+		} else if (!strncmp(arg, "--stop-at=", 10)) {
+			if (get_sha1(arg + 10, stop_at))
+				usage(rev_list_usage);
+			has_stop_at = 1;
 		} else {
 			commit_arg = arg;
 		}
 	}
 
 	if (!commit_arg || get_sha1(commit_arg, sha1))
-		usage("usage: rev-list [OPTION] commit-id\n"
-		      "  --max-count=nr\n"
-		      "  --max-age=epoch\n"
-		      "  --min-age=epoch\n");
+		usage(rev_list_usage);
 
 	commit = lookup_commit(sha1);
 	if (!commit || parse_commit(commit) < 0)
@@ -47,6 +57,8 @@ int main(int argc, char **argv)
 		if (max_count != -1 && !max_count--)
 			break;
 		printf("%s\n", sha1_to_hex(commit->object.sha1));
+		if (has_stop_at && !memcmp(stop_at, commit->object.sha1, 20))
+			break;
 	} while (list);
 	return 0;
 }
Thomas Gleixner· May 11, 2005, 20:30 UTC · re: Junio C Hamano · lore

Re: [PATCH] Stop git-rev-list at sha1 match

On Wed, 2005-05-11 at 13:03 -0700, Junio C Hamano wrote:
> Suggestion.  How about renaming "--to_sha1" to "--since"?  If
> you do not like "--since", then "--stop-at" would also be good.
No preference here :)
Show 7 quoted lines
> Suggestion.  Instead of running sha1_to_hex on the SHA1 of the
> commit and comparing strings for every commit you encounter, how
> about keeping 20-byte raw SHA1 of to_sha1 and doing memcmp of
> 20-byte?  That way you would also detect malformed --to-sha1
> parameter when you do the initial conversion upon argument
> parsing.  Also the argument parsing using get_sha1() would give
> you an added benefit of using mnemonics (tag and heads).

Makes sense. I just used the sha1_to_hex as it is called anyway for the printf

> What do you think about this revision?

You moved the stop behind the printf which is inconsistent to the other stop conditions, but thats a pure cosmetic question as long as it stays that way for ever.

Otherwise not objections.
tglx
Junio C Hamano· May 11, 2005, 21:54 UTC · re: Thomas Gleixner · lore

Re: [PATCH] Stop git-rev-list at sha1 match

>>>>> "TG" == Thomas Gleixner <tglx@linutronix.de> writes:

TG> You moved the stop behind the printf which is inconsistent to the other TG> stop conditions, but thats a pure cosmetic question as long as it stays TG> that way for ever.

While I work on the core GIT changes, I often find myself doing
    $ jit-log -l --since linus
    $ jit-log -l --since git-jc

to see what changes I have in my local work repository, and seeing the branching point (or origin) at the very end of the log made me feel assured that I am not losing anything in the log. But come to think of it, that is really an unnecessary thing and stopping _before_ the named commit would make more sense.

Here is a fixed version. I am CC'ing pasky hoping he would pick it up.

------------ Add --stop-at to git-rev-list command.

Signed-off-by: Junio C Hamano <junkio@cox.net>
---
Show changes to 5 files +200 −6

checkout-cache.c, rev-list.c, t/t0000.sh, t/t1000-checkout-cache.sh, t/t1001-checkout-cache.sh

--- a/checkout-cache.c
+++ b/checkout-cache.c
@@ -32,6 +32,8 @@
  * of "-a" causing problems (not possible in the above example,
  * but get used to it in scripting!).
  */
+#include <sys/types.h>
+#include <dirent.h>
 #include "cache.h"
 
 static int force = 0, quiet = 0, not_new = 0;
@@ -46,22 +48,67 @@ static void create_directories(const cha
 		len = slash - path;
 		memcpy(buf, path, len);
 		buf[len] = 0;
-		mkdir(buf, 0755);
+		if (mkdir(buf, 0755)) {
+			if (errno == EEXIST) {
+				struct stat st;
+				if (!lstat(buf, &st) && S_ISDIR(st.st_mode))
+					continue; /* ok */
+				if (force && !unlink(buf) && !mkdir(buf, 0755))
+					continue;
+			}
+			die("cannot create directory at %s", buf);
+		}
 	}
 	free(buf);
 }
 
+static void remove_subtree(const char *path)
+{
+	DIR *dir = opendir(path);
+	struct dirent *de;
+	char pathbuf[PATH_MAX];
+	char *name;
+	
+	if (!dir)
+		die("cannot opendir %s", path);
+	strcpy(pathbuf, path);
+	name = pathbuf + strlen(path);
+	*name++ = '/';
+	while ((de = readdir(dir)) != NULL) {
+		struct stat st;
+		if ((de->d_name[0] == '.') &&
+		    ((de->d_name[1] == 0) ||
+		     ((de->d_name[1] == '.') && de->d_name[2] == 0)))
+			continue;
+		strcpy(name, de->d_name);
+		if (lstat(pathbuf, &st))
+			die("cannot lstat %s", pathbuf);
+		if (S_ISDIR(st.st_mode))
+			remove_subtree(pathbuf);
+		else if (unlink(pathbuf))
+			die("cannot unlink %s", pathbuf);
+	}
+	closedir(dir);
+	if (rmdir(path))
+		die("cannot rmdir %s", path);
+}
+
 static int create_file(const char *path, unsigned int mode)
 {
 	int fd;
 
 	mode = (mode & 0100) ? 0777 : 0666;
+	create_directories(path);
 	fd = open(path, O_WRONLY | O_TRUNC | O_CREAT, mode);
 	if (fd < 0) {
-		if (errno == ENOENT) {
+		if ((errno == ENOENT) || (errno == ENOTDIR && force)) {
 			create_directories(path);
 			fd = open(path, O_WRONLY | O_TRUNC | O_CREAT, mode);
 		}
+		else if (errno == EISDIR && force) {
+			remove_subtree(path);
+			fd = open(path, O_WRONLY | O_TRUNC | O_CREAT, mode);
+		}
 	}
 	return fd;
 }
--- a/rev-list.c
+++ b/rev-list.c
@@ -1,12 +1,21 @@
 #include "cache.h"
 #include "commit.h"
 
+static const char *rev_list_usage = 
+"usage: rev-list [OPTION] commit-id\n"
+"  --max-count=nr\n"
+"  --max-age=epoch\n"
+"  --min-age=epoch\n"
+"  --stop-at=commit\n";
+
 int main(int argc, char **argv)
 {
 	unsigned char sha1[20];
 	struct commit_list *list = NULL;
 	struct commit *commit;
 	char *commit_arg = NULL;
+	unsigned char stop_at[20];
+	int has_stop_at = 0;
 	int i;
 	unsigned long max_age = -1;
 	unsigned long min_age = -1;
@@ -21,16 +30,17 @@ int main(int argc, char **argv)
 			max_age = atoi(arg + 10);
 		} else if (!strncmp(arg, "--min-age=", 10)) {
 			min_age = atoi(arg + 10);
+		} else if (!strncmp(arg, "--stop-at=", 10)) {
+			if (get_sha1(arg + 10, stop_at))
+				usage(rev_list_usage);
+			has_stop_at = 1;
 		} else {
 			commit_arg = arg;
 		}
 	}
 
 	if (!commit_arg || get_sha1(commit_arg, sha1))
-		usage("usage: rev-list [OPTION] commit-id\n"
-		      "  --max-count=nr\n"
-		      "  --max-age=epoch\n"
-		      "  --min-age=epoch\n");
+		usage(rev_list_usage);
 
 	commit = lookup_commit(sha1);
 	if (!commit || parse_commit(commit) < 0)
@@ -46,6 +56,8 @@ int main(int argc, char **argv)
 			break;
 		if (max_count != -1 && !max_count--)
 			break;
+		if (has_stop_at && !memcmp(stop_at, commit->object.sha1, 20))
+			break;
 		printf("%s\n", sha1_to_hex(commit->object.sha1));
 	} while (list);
 	return 0;
Created: t/t0000.sh (mode:100755)
--- /dev/null
+++ b/t/t0000.sh
@@ -0,0 +1,35 @@
+#!/bin/sh
+
+case "${verbose+set}" in
+set)	say= ;;
+*)	say=: ;;
+esac
+
+export LANG C
+unset AUTHOR_DATE
+unset AUTHOR_EMAIL
+unset AUTHOR_NAME
+unset COMMIT_AUTHOR_EMAIL
+unset COMMIT_AUTHOR_NAME
+unset GIT_ALTERNATE_OBJECT_DIRECTORIES
+unset GIT_AUTHOR_DATE
+unset GIT_AUTHOR_EMAIL
+unset GIT_AUTHOR_NAME
+unset GIT_COMMITTER_EMAIL
+unset GIT_COMMITTER_NAME
+unset GIT_DIFF_OPTS
+unset GIT_DIR
+unset GIT_EXTERNAL_DIFF
+unset GIT_INDEX_FILE
+unset GIT_OBJECT_DIRECTORY
+unset SHA1_FILE_DIRECTORIES
+unset SHA1_FILE_DIRECTORY
+
+# Test the binaries we have just built.
+PATH=$(pwd)/..:$PATH
+
+# Test repository
+test=test-repo
+rm -fr "$test"
+mkdir "$test"
+cd "$test"
Created: t/t1000-checkout-cache.sh (mode:100755)
--- /dev/null
+++ b/t/t1000-checkout-cache.sh
@@ -0,0 +1,39 @@
+#!/bin/sh
+
+. ./t0000.sh
+git-init-db 2>/dev/null || exit
+date >path0
+mkdir path1
+date >path1/file1
+git-update-cache --add path0 path1/file1
+$say git-ls-files --stage
+
+rm -fr path0 path1
+mkdir path0
+date >path0/file0
+date >path1
+$say git-ls-files --stage
+$say find path*
+
+echo >&2 "* checkout-cache sans -f"
+git-checkout-cache -a
+case "$?" in
+0)	echo >&2 "*** bug: should not have succeeded." ;;
+*)	echo >&2 "*** ok: failed as expected." ;;
+esac
+$say find path*
+
+echo >&2 "* checkout-cache with -f"
+git-checkout-cache -f -a
+case "$?" in
+0)	echo >&2 "*** ok: succeeded as expected." ;;
+*)	echo >&2 "*** bug: should have succeeded." ;;
+esac
+$say find path*
+if test -f path0 && test -d path1 && test -f path1/file1
+then
+	echo >&2 "*** ok: checked out correctly."
+else
+	echo >&2 "*** bug: checkout failed."
+	exit 1
+fi
Created: t/t1001-checkout-cache.sh (mode:100755)
--- /dev/null
+++ b/t/t1001-checkout-cache.sh
@@ -0,0 +1,61 @@
+#!/bin/sh
+
+. ./t0000.sh
+git-init-db 2>/dev/null || exit
+
+show_files() {
+	find path? -ls |
+	sed -e 's/^[0-9]* * [0-9]* * \([-bcdl]\)[^ ]* *[0-9]* *[^ ]* *[^ ]* *[0-9]* [A-Z][a-z][a-z] [0-9][0-9] [^ ]* /fs: \1 /'
+	git-ls-files --stage |
+	sed -e 's/^\([0-9]*\) [0-9a-f]* [0-3] /ca: \1 /'
+	git-ls-tree -r "$1" |
+	sed -e 's/^\([0-9]*\)	[^ ]*	[0-9a-f]*	/tr: \1 /'
+}
+
+mkdir path0
+date >path0/file0
+git-update-cache --add path0/file0
+echo >&2 "* initial state: one file under one directory"
+tree1=$(git-write-tree)
+$say show_files $tree1
+
+mkdir path1
+date >path1/file1
+git-update-cache --add path1/file1
+echo >&2 "* two directories with one file each"
+tree2=$(git-write-tree)
+$say show_files $tree2
+
+rm -fr path1
+git-read-tree -m $tree1
+git-checkout-cache -f -a
+echo >&2 "* go back to initial state"
+$say show_files $tree1
+
+ln -s path0 path1
+git-update-cache --add path1
+echo >&2 "* a symlink where the other side would create a directory."
+tree3=$(git-write-tree)
+$say show_files $tree3
+
+# Morten says "Got that?" here.
+
+git-read-tree $tree2
+git-checkout-cache -f -a
+case "$?" in
+0)	echo >&2 "*** ok: succeeded as expected." ;;
+*)	echo >&2 "*** bug: should have succeeded." ;;
+esac
+echo >&2 "* read tree2 and checkout"
+$say show_files $tree2
+
+if test ! -h path0 && test -d path0 &&
+   test ! -h path1 && test -d path1 &&
+   test ! -h path0/file0 && test -f path0/file0 &&
+   test ! -h path1/file1 && test -f path1/file1
+then
+    echo >&2 "*** ok: checked out correctly."
+else
+    echo >&2 "*** bug: did not check out correctly."
+    exit 1
+fi
------------------------------------------------
Petr Baudis· May 11, 2005, 22:17 UTC · re: Junio C Hamano · lore

Re: [PATCH] Stop git-rev-list at sha1 match

Dear diary, on Wed, May 11, 2005 at 11:54:11PM CEST, I got a letter where Junio C Hamano <junkio@cox.net> told me that...

Show 20 quoted lines
> >>>>> "TG" == Thomas Gleixner <tglx@linutronix.de> writes:
> 
> TG> You moved the stop behind the printf which is inconsistent to the other
> TG> stop conditions, but thats a pure cosmetic question as long as it stays
> TG> that way for ever. 
> 
> While I work on the core GIT changes, I often find myself doing
> 
>     $ jit-log -l --since linus
>     $ jit-log -l --since git-jc
> 
> to see what changes I have in my local work repository, and
> seeing the branching point (or origin) at the very end of the
> log made me feel assured that I am not losing anything in the
> log.  But come to think of it, that is really an unnecessary
> thing and stopping _before_ the named commit would make more
> sense.
> 
> Here is a fixed version.  I am CC'ing pasky hoping he would pick
> it up.
Yes, looks better and more consistent with the rest of the stuff.

But the very fact that you want this makes me *quite* nervous - I think this is bad thing to do. The problem is, for something like

     o
     | \
     o  |
     |  o
     |  o
     o /
     o
    ------
it will show the merged revisions properly, but for
     o
     | \
     o  |
    ------
     |  o
     |  o
     o /
     o
it won't show the full merge. Whilst when you do
	*-log --since foo

I think you mean it to show everything going into the tree since foo - that would include the whole branch you cut off now.

Thomas, what are you going to use it for?
> Add --stop-at to git-rev-list command.
> 
> Signed-off-by: Junio C Hamano <junkio@cox.net>

I liked the previous patch revision commit message much better, I have to admit. ;-)

> ---
> --- a/checkout-cache.c
> +++ b/checkout-cache.c
I assume this is irrelevant here?
> --- a/rev-list.c
> +++ b/rev-list.c
Looks ok.

Could you please also update the documentation appropriately? (If we have it, let's keep it up to date.)

> Created: t/t0000.sh (mode:100755)
> --- /dev/null
> +++ b/t/t0000.sh
You want this in too?

Starting to build a testsuite sounds like a good idea, but we should probably first devise some calling convention etc. I personally suck at automated testing.

-- 
				Petr "Pasky" Baudis
Stuff: http://pasky.or.cz/
C++: an octopus made by nailing extra legs onto a dog. -- Steve Taylor
Thomas Gleixner· May 11, 2005, 22:49 UTC · re: Petr Baudis · lore

Re: [PATCH] Stop git-rev-list at sha1 match

On Thu, 2005-05-12 at 00:17 +0200, Petr Baudis wrote:
Show 6 quoted lines
> But the very fact that you want this makes me *quite* nervous - I think
> this is bad thing to do. The problem is, for something like
> it won't show the full merge. 
> 
> I think you mean it to show everything going into the tree since foo -
> that would include the whole branch you cut off now.
>From a SCM POV it does not matter.
Rn   o
     | \
Rn-1 o  |
     |  o Mn
     |  o Mn-1
Rn-2 o /
Rn-3 o

If you are in Repository R, then tracking Rn to Rn-123 gives you a linear result depending on the stop point you chose. Rn ---- Stop = Rn-1 Rn-1 ---- Stop = Rn-2 Rn-2 ---- Stop = Rn-3

The diff between Rn and Rn-1 contains always the changes merged from M
> Thomas, what are you going to use it for?
Displaing the the changes between commit shaX and shaY :)
tglx
Petr Baudis· May 11, 2005, 22:50 UTC · re: Thomas Gleixner · lore

Re: [PATCH] Stop git-rev-list at sha1 match

Dear diary, on Thu, May 12, 2005 at 12:49:02AM CEST, I got a letter where Thomas Gleixner <tglx@linutronix.de> told me that...

Show 14 quoted lines
> Rn   o
>      | \
> Rn-1 o  |
>      |  o Mn
>      |  o Mn-1
> Rn-2 o /
> Rn-3 o
> 
> If you are in Repository R, then tracking Rn to Rn-123 gives you a
> linear result depending on the stop point you chose.
> Rn
> ---- Stop = Rn-1
> Rn-1
> ---- Stop = Rn-2

Mn Mn-1

> Rn-2
> ---- Stop = Rn-3
> 
> The diff between Rn and Rn-1 contains always the changes merged from M

Yes, but you get the merge commits again since rev-list follows all the parents.

-- 
				Petr "Pasky" Baudis
Stuff: http://pasky.or.cz/
C++: an octopus made by nailing extra legs onto a dog. -- Steve Taylor
Thomas Gleixner· May 11, 2005, 23:08 UTC · re: Petr Baudis · lore

Re: [PATCH] Stop git-rev-list at sha1 match

On Thu, 2005-05-12 at 00:50 +0200, Petr Baudis wrote:
Show 15 quoted lines
> > Rn
> > ---- Stop = Rn-1
> > Rn-1
> > ---- Stop = Rn-2
> 
> Mn
> Mn-1
> 
> > Rn-2
> > ---- Stop = Rn-3
> > 
> > The diff between Rn and Rn-1 contains always the changes merged from M
> 
> Yes, but you get the merge commits again since rev-list follows all the
> parents.

That's plain wrong. The Mn(1) change hit repository r between revision Rn and Rn-1 and nowhere else.

Date is irrelevant. The only relevant thing is the parent child(s) relationship.

What you get doing this is history cluttering. In the repository R it is completely irrelevant when Mn resp. Mn-1 was created. The only relevant point is when it was merged into repository R.

Bitkeeper does the same bogus thing to make changesets appear in a linear order. Look at the changeset logs. If you diff the versions exported by bitkeeper then you get complete nonsense.

Please do not make the same mistake. 
tglx
Petr Baudis· May 11, 2005, 23:44 UTC · re: Thomas Gleixner · lore

Re: [PATCH] Stop git-rev-list at sha1 match

Dear diary, on Thu, May 12, 2005 at 01:08:34AM CEST, I got a letter where Thomas Gleixner <tglx@linutronix.de> told me that...

Show 22 quoted lines
> On Thu, 2005-05-12 at 00:50 +0200, Petr Baudis wrote:
> > > Rn
> > > ---- Stop = Rn-1
> > > Rn-1
> > > ---- Stop = Rn-2
> > 
> > Mn
> > Mn-1
> > 
> > > Rn-2
> > > ---- Stop = Rn-3
> > > 
> > > The diff between Rn and Rn-1 contains always the changes merged from M
> > 
> > Yes, but you get the merge commits again since rev-list follows all the
> > parents.
> 
> That's plain wrong. The Mn(1) change hit repository r between revision
> Rn and Rn-1 and nowhere else. 
> 
> Date is irrelevant. The only relevant thing is the parent child(s)
> relationship.

What I described is just how rev-list works (now), nothing more. This is what you get when you use rev-list.

Please see the thread of
5730     Apr 27 H. Peter Anvin  ( 0.2K) kernel.org now has gitweb installed

for extensive discussion on how (it is impossible or very hard) to do better.

So how would you order the list of commits?
-- 
				Petr "Pasky" Baudis
Stuff: http://pasky.or.cz/
C++: an octopus made by nailing extra legs onto a dog. -- Steve Taylor
Thomas Gleixner· May 12, 2005, 00:31 UTC · re: Petr Baudis · lore

Re: [PATCH] Stop git-rev-list at sha1 match

On Thu, 2005-05-12 at 01:44 +0200, Petr Baudis wrote:
> for extensive discussion on how (it is impossible or very hard) to do
> better.
:)
> So how would you order the list of commits?
Rn
  merged Mn
  merged Mn-1
Rn-1
....

That's the relevant information in repository R. Looking at it from repository M after M updated to Rn

(Mn+1) == Rn	; Mn+1 is not created due to head forward
  merged Rn
  .. 
  merged Rn-3
Mn
Mn-1

Thats the historical correct ordering from a repository point of view. Thats the only relevant information IMNSHO.

The dates of author and committer are retrievable in each repository, but the order of commits are not.

tglx
Petr Baudis· May 13, 2005, 05:26 UTC · re: Thomas Gleixner · lore

Re: [PATCH] Stop git-rev-list at sha1 match

Dear diary, on Thu, May 12, 2005 at 02:31:13AM CEST, I got a letter where Thomas Gleixner <tglx@linutronix.de> told me that...

Show 26 quoted lines
> On Thu, 2005-05-12 at 01:44 +0200, Petr Baudis wrote:
> > for extensive discussion on how (it is impossible or very hard) to do
> > better.
> 
> :)
> 
> > So how would you order the list of commits?
> 
> Rn
>   merged Mn
>   merged Mn-1
> Rn-1
> ....
> 
> That's the relevant information in repository R. Looking at it from
> repository M after M updated to Rn
> 
> (Mn+1) == Rn	; Mn+1 is not created due to head forward
>   merged Rn
>   .. 
>   merged Rn-3
> Mn
> Mn-1
> 
> Thats the historical correct ordering from a repository point of view.
> Thats the only relevant information IMNSHO.

But it is impossible to reconstruct without the repoid or something. So my point that it makes no sense and is actually dangerous with the current rev-list output order holds.

-- 
				Petr "Pasky" Baudis
Stuff: http://pasky.or.cz/
C++: an octopus made by nailing extra legs onto a dog. -- Steve Taylor
Junio C Hamano· May 12, 2005, 01:54 UTC · re: Petr Baudis · lore

Re: [PATCH] Stop git-rev-list at sha1 match

>>>>> "PB" == Petr Baudis <pasky@ucw.cz> writes:
PB> it will show the merged revisions properly, but for

PB> o PB> | \ PB> o | PB> ------ PB> | o PB> | o PB> o / PB> o

PB> it won't show the full merge. Whilst when you do
PB> 	*-log --since foo

PB> I think you mean it to show everything going into the tree since foo - PB> that would include the whole branch you cut off now.

I use "rev-tree HEAD ^$(git-merge-base HEAD foo)" for this kind of thing, so rev-list does not really matter.

>> --- a/checkout-cache.c
>> +++ b/checkout-cache.c
PB> I assume this is irrelevant here?
Sorry for sending a dirty patch in.  Will fix it up.
Junio C Hamano· May 12, 2005, 02:11 UTC · re: Junio C Hamano · lore

Re: [PATCH] Stop git-rev-list at sha1 match

>>>>> "JCH" == Junio C Hamano <junkio@cox.net> writes:
>>>>> "PB" == Petr Baudis <pasky@ucw.cz> writes:
>>> --- a/checkout-cache.c
>>> +++ b/checkout-cache.c

PB> I assume this is irrelevant here? JCH> Sorry for sending a dirty patch in. Will fix it up.

------------ Introduce "rev-list --stop-at=<commit>".

Additional option, --stop-at=<commit>, is introduced. The git-rev-list output stops just before showing the named commit.

This is based on Thoms Gleixner's patch but slightly reworked, with documentation updates.

Signed-off-by: Junio C Hamano <junkio@cox.net>
---

Documentation/git-rev-list.txt | 18 +++++++++++++++++- rev-list.c | 20 ++++++++++++++++---- 2 files changed, 33 insertions(+), 5 deletions(-)

Show changes to 2 files +33 −5

Documentation/git-rev-list.txt, rev-list.c

--- a/Documentation/git-rev-list.txt
+++ b/Documentation/git-rev-list.txt
@@ -9,7 +9,10 @@
 
 SYNOPSIS
 --------
-'git-rev-list' <commit>
+'git-rev-list'	[--max-count=<number>]
+		[--max-age=<unixtime>]
+		[--min-age=<unixtime>]
+		[--stop-at=<commit>] <commit>
 
 DESCRIPTION
 -----------
@@ -17,6 +20,19 @@
 given commit, taking ancestry relationship into account.  This is
 useful to produce human-readable log output.
 
+OPTIONS
+-------
+--max-count=<number>::
+	Stop after showing <number> commits.
+
+--max-age=<unixtime>::
+	Stop after showing commit made before <unixtime>.
+
+--min-age=<unixtime>::
+	Skip until commit made before <unixtime>.
+
+--stop-at=<commit>::
+	Stop just before showing <commit>.
 
 Author
 ------
--- a/rev-list.c
+++ b/rev-list.c
@@ -1,12 +1,21 @@
 #include "cache.h"
 #include "commit.h"
 
+static const char *rev_list_usage = 
+"usage: rev-list [OPTION] commit-id\n"
+"  --max-count=nr\n"
+"  --max-age=epoch\n"
+"  --min-age=epoch\n"
+"  --stop-at=commit\n";
+
 int main(int argc, char **argv)
 {
 	unsigned char sha1[20];
 	struct commit_list *list = NULL;
 	struct commit *commit;
 	char *commit_arg = NULL;
+	unsigned char stop_at[20];
+	int has_stop_at = 0;
 	int i;
 	unsigned long max_age = -1;
 	unsigned long min_age = -1;
@@ -21,16 +30,17 @@
 			max_age = atoi(arg + 10);
 		} else if (!strncmp(arg, "--min-age=", 10)) {
 			min_age = atoi(arg + 10);
+		} else if (!strncmp(arg, "--stop-at=", 10)) {
+			if (get_sha1(arg + 10, stop_at))
+				usage(rev_list_usage);
+			has_stop_at = 1;
 		} else {
 			commit_arg = arg;
 		}
 	}
 
 	if (!commit_arg || get_sha1(commit_arg, sha1))
-		usage("usage: rev-list [OPTION] commit-id\n"
-		      "  --max-count=nr\n"
-		      "  --max-age=epoch\n"
-		      "  --min-age=epoch\n");
+		usage(rev_list_usage);
 
 	commit = lookup_commit(sha1);
 	if (!commit || parse_commit(commit) < 0)
@@ -46,6 +56,8 @@
 			break;
 		if (max_count != -1 && !max_count--)
 			break;
+		if (has_stop_at && !memcmp(stop_at, commit->object.sha1, 20))
+			break;
 		printf("%s\n", sha1_to_hex(commit->object.sha1));
 	} while (list);
 	return 0;
------------------------------------------------

← back to recent threads