{"thread":{"id":"574","subject":"[PATCH] Stop git-rev-list at sha1 match","startedAt":"2005-05-11T19:24:16Z","lastAt":"2005-05-13T05:26:33Z","messageCount":13,"participants":["Thomas Gleixner","Junio C Hamano","Petr Baudis"],"isPatch":true,"patchVersion":1,"patchTotal":null},"messages":[{"id":"3057","messageId":"1115839456.22180.79.camel@tglx","threadId":"574","inReplyTo":null,"subject":"[PATCH] Stop git-rev-list at sha1 match","fromName":"Thomas Gleixner","fromEmail":"tglx@linutronix.de","sentAt":"2005-05-11T19:24:16Z","receivedAt":"2005-05-11T19:24:16Z","isPatch":true,"sender":{"key":"tglx@linutronix.de","avatar":null},"body":"The patch adds an option to stop the output of git-rev-list\non a sha1 match. \n\nSigned-Off: Thomas Gleixner <tglx@linutronix.de>\n\n--- a/rev-list.c\n+++ b/rev-list.c\n@@ -7,6 +7,8 @@ int main(int argc, char **argv)\n \tstruct commit_list *list = NULL;\n \tstruct commit *commit;\n \tchar *commit_arg = NULL;\n+\tchar *sha1hex;\n+\tchar *to_sha1 = NULL;\n \tint i;\n \tunsigned long max_age = -1;\n \tunsigned long min_age = -1;\n@@ -21,6 +23,8 @@ int main(int argc, char **argv)\n \t\t\tmax_age = atoi(arg + 10);\n \t\t} else if (!strncmp(arg, \"--min-age=\", 10)) {\n \t\t\tmin_age = atoi(arg + 10);\n+\t\t} else if (!strncmp(arg, \"--to_sha1=\", 10)) {\n+\t\t\tto_sha1 = arg + 10;\n \t\t} else {\n \t\t\tcommit_arg = arg;\n \t\t}\n@@ -30,7 +34,8 @@ int main(int argc, char **argv)\n \t\tusage(\"usage: rev-list [OPTION] commit-id\\n\"\n \t\t      \"  --max-count=nr\\n\"\n \t\t      \"  --max-age=epoch\\n\"\n-\t\t      \"  --min-age=epoch\\n\");\n+\t\t      \"  --min-age=epoch\\n\"\n+\t\t      \"  --to-sha1=sha1\\n\");\n \n \tcommit = lookup_commit(sha1);\n \tif (!commit || parse_commit(commit) < 0)\n@@ -46,7 +51,10 @@ int main(int argc, char **argv)\n \t\t\tbreak;\n \t\tif (max_count != -1 && !max_count--)\n \t\t\tbreak;\n-\t\tprintf(\"%s\\n\", sha1_to_hex(commit->object.sha1));\n+\t\tsha1hex = sha1_to_hex(commit->object.sha1);\n+\t\tif (to_sha1 != NULL && strcmp(to_sha1, sha1hex) == 0)\n+\t\t\tbreak;\n+\t\tprintf(\"%s\\n\", sha1hex);\n \t} while (list);\n \treturn 0;\n }\n\n\n"},{"id":"3059","messageId":"7vy8alr0mz.fsf@assigned-by-dhcp.cox.net","threadId":"574","inReplyTo":"1115839456.22180.79.camel@tglx","subject":"Re: [PATCH] Stop git-rev-list at sha1 match","fromName":"Junio C Hamano","fromEmail":"junkio@cox.net","sentAt":"2005-05-11T20:03:16Z","receivedAt":"2005-05-11T20:03:16Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":">>>>> \"TG\" == Thomas Gleixner <tglx@linutronix.de> writes:\n\nTG> The patch adds an option to stop the output of git-rev-list\nTG> on a sha1 match. \n\nOne minor nit and two suggestions.  Otherwise looks good.\n\nTG> Signed-Off: Thomas Gleixner <tglx@linutronix.de>\n\nNit.  Please spell it \"Signed-off-by: \".  I have seen some\npeople spell \"off\" with capital \"O\" so I guess it is also\npermitted.\n\nTG>  \t\t} else if (!strncmp(arg, \"--min-age=\", 10)) {\nTG>  \t\t\tmin_age = atoi(arg + 10);\nTG> +\t\t} else if (!strncmp(arg, \"--to_sha1=\", 10)) {\nTG> +\t\t\tto_sha1 = arg + 10;\n\nSuggestion.  How about renaming \"--to_sha1\" to \"--since\"?  If\nyou do not like \"--since\", then \"--stop-at\" would also be good.\n\nThe point being that I do not think we need to emphasize that\nthe 40-character object IDs are produced by an algorithm that\nhappens to use SHA1 hash in one of the steps of the computation.\nThat is just an implementation detail and irrelevant to the\nuser.  What you are accepting here is really the object ID of\nthe commit object.\n\nAt the very least, \"--to-sha1\" (hyphen not underscore) for\nconsistency, please.\n\nTG> +\t\tsha1hex = sha1_to_hex(commit->object.sha1);\nTG> +\t\tif (to_sha1 != NULL && strcmp(to_sha1, sha1hex) == 0)\nTG> +\t\t\tbreak;\n\nSuggestion.  Instead of running sha1_to_hex on the SHA1 of the\ncommit and comparing strings for every commit you encounter, how\nabout keeping 20-byte raw SHA1 of to_sha1 and doing memcmp of\n20-byte?  That way you would also detect malformed --to-sha1\nparameter when you do the initial conversion upon argument\nparsing.  Also the argument parsing using get_sha1() would give\nyou an added benefit of using mnemonics (tag and heads).\n\nWhat do you think about this revision?\n\n----------------------------------------\n[PATCH] Introduce \"rev-list --stop-at=<commit>\".\n\nAdditional option, --stop-at=<commit>, is introduced.  The\nrev-list output stops after showing the named commit.\n\nThis is based on Thoms Gleixner's patch but slightly reworked.\n\nSigned-off-by: Junio C Hamano <junkio@cox.net> \n---\n--- a/rev-list.c\n+++ b/rev-list.c\n@@ -1,12 +1,21 @@\n #include \"cache.h\"\n #include \"commit.h\"\n \n+static const char *rev_list_usage = \n+\"usage: rev-list [OPTION] commit-id\\n\"\n+\"  --max-count=nr\\n\"\n+\"  --max-age=epoch\\n\"\n+\"  --min-age=epoch\\n\"\n+\"  --stop-at=commit\\n\";\n+\n int main(int argc, char **argv)\n {\n \tunsigned char sha1[20];\n \tstruct commit_list *list = NULL;\n \tstruct commit *commit;\n \tchar *commit_arg = NULL;\n+\tunsigned char stop_at[20];\n+\tint has_stop_at = 0;\n \tint i;\n \tunsigned long max_age = -1;\n \tunsigned long min_age = -1;\n@@ -21,16 +30,17 @@ int main(int argc, char **argv)\n \t\t\tmax_age = atoi(arg + 10);\n \t\t} else if (!strncmp(arg, \"--min-age=\", 10)) {\n \t\t\tmin_age = atoi(arg + 10);\n+\t\t} else if (!strncmp(arg, \"--stop-at=\", 10)) {\n+\t\t\tif (get_sha1(arg + 10, stop_at))\n+\t\t\t\tusage(rev_list_usage);\n+\t\t\thas_stop_at = 1;\n \t\t} else {\n \t\t\tcommit_arg = arg;\n \t\t}\n \t}\n \n \tif (!commit_arg || get_sha1(commit_arg, sha1))\n-\t\tusage(\"usage: rev-list [OPTION] commit-id\\n\"\n-\t\t      \"  --max-count=nr\\n\"\n-\t\t      \"  --max-age=epoch\\n\"\n-\t\t      \"  --min-age=epoch\\n\");\n+\t\tusage(rev_list_usage);\n \n \tcommit = lookup_commit(sha1);\n \tif (!commit || parse_commit(commit) < 0)\n@@ -47,6 +57,8 @@ int main(int argc, char **argv)\n \t\tif (max_count != -1 && !max_count--)\n \t\t\tbreak;\n \t\tprintf(\"%s\\n\", sha1_to_hex(commit->object.sha1));\n+\t\tif (has_stop_at && !memcmp(stop_at, commit->object.sha1, 20))\n+\t\t\tbreak;\n \t} while (list);\n \treturn 0;\n }\n\n\n\n"},{"id":"3060","messageId":"1115843429.22180.90.camel@tglx","threadId":"574","inReplyTo":"7vy8alr0mz.fsf@assigned-by-dhcp.cox.net","subject":"Re: [PATCH] Stop git-rev-list at sha1 match","fromName":"Thomas Gleixner","fromEmail":"tglx@linutronix.de","sentAt":"2005-05-11T20:30:29Z","receivedAt":"2005-05-11T20:30:29Z","isPatch":true,"sender":{"key":"tglx@linutronix.de","avatar":null},"body":"On Wed, 2005-05-11 at 13:03 -0700, Junio C Hamano wrote:\n> Suggestion.  How about renaming \"--to_sha1\" to \"--since\"?  If\n> you do not like \"--since\", then \"--stop-at\" would also be good.\n\nNo preference here :)\n\n> Suggestion.  Instead of running sha1_to_hex on the SHA1 of the\n> commit and comparing strings for every commit you encounter, how\n> about keeping 20-byte raw SHA1 of to_sha1 and doing memcmp of\n> 20-byte?  That way you would also detect malformed --to-sha1\n> parameter when you do the initial conversion upon argument\n> parsing.  Also the argument parsing using get_sha1() would give\n> you an added benefit of using mnemonics (tag and heads).\n\nMakes sense. I just used the sha1_to_hex as it is called anyway for the\nprintf \n\n> What do you think about this revision?\n\nYou moved the stop behind the printf which is inconsistent to the other\nstop conditions, but thats a pure cosmetic question as long as it stays\nthat way for ever. \n\nOtherwise not objections.\n\ntglx\n\n\n"},{"id":"3067","messageId":"7vis1pqvi4.fsf@assigned-by-dhcp.cox.net","threadId":"574","inReplyTo":"1115843429.22180.90.camel@tglx","subject":"Re: [PATCH] Stop git-rev-list at sha1 match","fromName":"Junio C Hamano","fromEmail":"junkio@cox.net","sentAt":"2005-05-11T21:54:11Z","receivedAt":"2005-05-11T21:54:11Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":">>>>> \"TG\" == Thomas Gleixner <tglx@linutronix.de> writes:\n\nTG> You moved the stop behind the printf which is inconsistent to the other\nTG> stop conditions, but thats a pure cosmetic question as long as it stays\nTG> that way for ever. \n\nWhile I work on the core GIT changes, I often find myself doing\n\n    $ jit-log -l --since linus\n    $ jit-log -l --since git-jc\n\nto see what changes I have in my local work repository, and\nseeing the branching point (or origin) at the very end of the\nlog made me feel assured that I am not losing anything in the\nlog.  But come to think of it, that is really an unnecessary\nthing and stopping _before_ the named commit would make more\nsense.\n\nHere is a fixed version.  I am CC'ing pasky hoping he would pick\nit up.\n\n------------\nAdd --stop-at to git-rev-list command.\n\nSigned-off-by: Junio C Hamano <junkio@cox.net>\n---\n--- a/checkout-cache.c\n+++ b/checkout-cache.c\n@@ -32,6 +32,8 @@\n  * of \"-a\" causing problems (not possible in the above example,\n  * but get used to it in scripting!).\n  */\n+#include <sys/types.h>\n+#include <dirent.h>\n #include \"cache.h\"\n \n static int force = 0, quiet = 0, not_new = 0;\n@@ -46,22 +48,67 @@ static void create_directories(const cha\n \t\tlen = slash - path;\n \t\tmemcpy(buf, path, len);\n \t\tbuf[len] = 0;\n-\t\tmkdir(buf, 0755);\n+\t\tif (mkdir(buf, 0755)) {\n+\t\t\tif (errno == EEXIST) {\n+\t\t\t\tstruct stat st;\n+\t\t\t\tif (!lstat(buf, &st) && S_ISDIR(st.st_mode))\n+\t\t\t\t\tcontinue; /* ok */\n+\t\t\t\tif (force && !unlink(buf) && !mkdir(buf, 0755))\n+\t\t\t\t\tcontinue;\n+\t\t\t}\n+\t\t\tdie(\"cannot create directory at %s\", buf);\n+\t\t}\n \t}\n \tfree(buf);\n }\n \n+static void remove_subtree(const char *path)\n+{\n+\tDIR *dir = opendir(path);\n+\tstruct dirent *de;\n+\tchar pathbuf[PATH_MAX];\n+\tchar *name;\n+\t\n+\tif (!dir)\n+\t\tdie(\"cannot opendir %s\", path);\n+\tstrcpy(pathbuf, path);\n+\tname = pathbuf + strlen(path);\n+\t*name++ = '/';\n+\twhile ((de = readdir(dir)) != NULL) {\n+\t\tstruct stat st;\n+\t\tif ((de->d_name[0] == '.') &&\n+\t\t    ((de->d_name[1] == 0) ||\n+\t\t     ((de->d_name[1] == '.') && de->d_name[2] == 0)))\n+\t\t\tcontinue;\n+\t\tstrcpy(name, de->d_name);\n+\t\tif (lstat(pathbuf, &st))\n+\t\t\tdie(\"cannot lstat %s\", pathbuf);\n+\t\tif (S_ISDIR(st.st_mode))\n+\t\t\tremove_subtree(pathbuf);\n+\t\telse if (unlink(pathbuf))\n+\t\t\tdie(\"cannot unlink %s\", pathbuf);\n+\t}\n+\tclosedir(dir);\n+\tif (rmdir(path))\n+\t\tdie(\"cannot rmdir %s\", path);\n+}\n+\n static int create_file(const char *path, unsigned int mode)\n {\n \tint fd;\n \n \tmode = (mode & 0100) ? 0777 : 0666;\n+\tcreate_directories(path);\n \tfd = open(path, O_WRONLY | O_TRUNC | O_CREAT, mode);\n \tif (fd < 0) {\n-\t\tif (errno == ENOENT) {\n+\t\tif ((errno == ENOENT) || (errno == ENOTDIR && force)) {\n \t\t\tcreate_directories(path);\n \t\t\tfd = open(path, O_WRONLY | O_TRUNC | O_CREAT, mode);\n \t\t}\n+\t\telse if (errno == EISDIR && force) {\n+\t\t\tremove_subtree(path);\n+\t\t\tfd = open(path, O_WRONLY | O_TRUNC | O_CREAT, mode);\n+\t\t}\n \t}\n \treturn fd;\n }\n--- a/rev-list.c\n+++ b/rev-list.c\n@@ -1,12 +1,21 @@\n #include \"cache.h\"\n #include \"commit.h\"\n \n+static const char *rev_list_usage = \n+\"usage: rev-list [OPTION] commit-id\\n\"\n+\"  --max-count=nr\\n\"\n+\"  --max-age=epoch\\n\"\n+\"  --min-age=epoch\\n\"\n+\"  --stop-at=commit\\n\";\n+\n int main(int argc, char **argv)\n {\n \tunsigned char sha1[20];\n \tstruct commit_list *list = NULL;\n \tstruct commit *commit;\n \tchar *commit_arg = NULL;\n+\tunsigned char stop_at[20];\n+\tint has_stop_at = 0;\n \tint i;\n \tunsigned long max_age = -1;\n \tunsigned long min_age = -1;\n@@ -21,16 +30,17 @@ int main(int argc, char **argv)\n \t\t\tmax_age = atoi(arg + 10);\n \t\t} else if (!strncmp(arg, \"--min-age=\", 10)) {\n \t\t\tmin_age = atoi(arg + 10);\n+\t\t} else if (!strncmp(arg, \"--stop-at=\", 10)) {\n+\t\t\tif (get_sha1(arg + 10, stop_at))\n+\t\t\t\tusage(rev_list_usage);\n+\t\t\thas_stop_at = 1;\n \t\t} else {\n \t\t\tcommit_arg = arg;\n \t\t}\n \t}\n \n \tif (!commit_arg || get_sha1(commit_arg, sha1))\n-\t\tusage(\"usage: rev-list [OPTION] commit-id\\n\"\n-\t\t      \"  --max-count=nr\\n\"\n-\t\t      \"  --max-age=epoch\\n\"\n-\t\t      \"  --min-age=epoch\\n\");\n+\t\tusage(rev_list_usage);\n \n \tcommit = lookup_commit(sha1);\n \tif (!commit || parse_commit(commit) < 0)\n@@ -46,6 +56,8 @@ int main(int argc, char **argv)\n \t\t\tbreak;\n \t\tif (max_count != -1 && !max_count--)\n \t\t\tbreak;\n+\t\tif (has_stop_at && !memcmp(stop_at, commit->object.sha1, 20))\n+\t\t\tbreak;\n \t\tprintf(\"%s\\n\", sha1_to_hex(commit->object.sha1));\n \t} while (list);\n \treturn 0;\nCreated: t/t0000.sh (mode:100755)\n--- /dev/null\n+++ b/t/t0000.sh\n@@ -0,0 +1,35 @@\n+#!/bin/sh\n+\n+case \"${verbose+set}\" in\n+set)\tsay= ;;\n+*)\tsay=: ;;\n+esac\n+\n+export LANG C\n+unset AUTHOR_DATE\n+unset AUTHOR_EMAIL\n+unset AUTHOR_NAME\n+unset COMMIT_AUTHOR_EMAIL\n+unset COMMIT_AUTHOR_NAME\n+unset GIT_ALTERNATE_OBJECT_DIRECTORIES\n+unset GIT_AUTHOR_DATE\n+unset GIT_AUTHOR_EMAIL\n+unset GIT_AUTHOR_NAME\n+unset GIT_COMMITTER_EMAIL\n+unset GIT_COMMITTER_NAME\n+unset GIT_DIFF_OPTS\n+unset GIT_DIR\n+unset GIT_EXTERNAL_DIFF\n+unset GIT_INDEX_FILE\n+unset GIT_OBJECT_DIRECTORY\n+unset SHA1_FILE_DIRECTORIES\n+unset SHA1_FILE_DIRECTORY\n+\n+# Test the binaries we have just built.\n+PATH=$(pwd)/..:$PATH\n+\n+# Test repository\n+test=test-repo\n+rm -fr \"$test\"\n+mkdir \"$test\"\n+cd \"$test\"\nCreated: t/t1000-checkout-cache.sh (mode:100755)\n--- /dev/null\n+++ b/t/t1000-checkout-cache.sh\n@@ -0,0 +1,39 @@\n+#!/bin/sh\n+\n+. ./t0000.sh\n+git-init-db 2>/dev/null || exit\n+date >path0\n+mkdir path1\n+date >path1/file1\n+git-update-cache --add path0 path1/file1\n+$say git-ls-files --stage\n+\n+rm -fr path0 path1\n+mkdir path0\n+date >path0/file0\n+date >path1\n+$say git-ls-files --stage\n+$say find path*\n+\n+echo >&2 \"* checkout-cache sans -f\"\n+git-checkout-cache -a\n+case \"$?\" in\n+0)\techo >&2 \"*** bug: should not have succeeded.\" ;;\n+*)\techo >&2 \"*** ok: failed as expected.\" ;;\n+esac\n+$say find path*\n+\n+echo >&2 \"* checkout-cache with -f\"\n+git-checkout-cache -f -a\n+case \"$?\" in\n+0)\techo >&2 \"*** ok: succeeded as expected.\" ;;\n+*)\techo >&2 \"*** bug: should have succeeded.\" ;;\n+esac\n+$say find path*\n+if test -f path0 && test -d path1 && test -f path1/file1\n+then\n+\techo >&2 \"*** ok: checked out correctly.\"\n+else\n+\techo >&2 \"*** bug: checkout failed.\"\n+\texit 1\n+fi\nCreated: t/t1001-checkout-cache.sh (mode:100755)\n--- /dev/null\n+++ b/t/t1001-checkout-cache.sh\n@@ -0,0 +1,61 @@\n+#!/bin/sh\n+\n+. ./t0000.sh\n+git-init-db 2>/dev/null || exit\n+\n+show_files() {\n+\tfind path? -ls |\n+\tsed -e 's/^[0-9]* * [0-9]* * \\([-bcdl]\\)[^ ]* *[0-9]* *[^ ]* *[^ ]* *[0-9]* [A-Z][a-z][a-z] [0-9][0-9] [^ ]* /fs: \\1 /'\n+\tgit-ls-files --stage |\n+\tsed -e 's/^\\([0-9]*\\) [0-9a-f]* [0-3] /ca: \\1 /'\n+\tgit-ls-tree -r \"$1\" |\n+\tsed -e 's/^\\([0-9]*\\)\t[^ ]*\t[0-9a-f]*\t/tr: \\1 /'\n+}\n+\n+mkdir path0\n+date >path0/file0\n+git-update-cache --add path0/file0\n+echo >&2 \"* initial state: one file under one directory\"\n+tree1=$(git-write-tree)\n+$say show_files $tree1\n+\n+mkdir path1\n+date >path1/file1\n+git-update-cache --add path1/file1\n+echo >&2 \"* two directories with one file each\"\n+tree2=$(git-write-tree)\n+$say show_files $tree2\n+\n+rm -fr path1\n+git-read-tree -m $tree1\n+git-checkout-cache -f -a\n+echo >&2 \"* go back to initial state\"\n+$say show_files $tree1\n+\n+ln -s path0 path1\n+git-update-cache --add path1\n+echo >&2 \"* a symlink where the other side would create a directory.\"\n+tree3=$(git-write-tree)\n+$say show_files $tree3\n+\n+# Morten says \"Got that?\" here.\n+\n+git-read-tree $tree2\n+git-checkout-cache -f -a\n+case \"$?\" in\n+0)\techo >&2 \"*** ok: succeeded as expected.\" ;;\n+*)\techo >&2 \"*** bug: should have succeeded.\" ;;\n+esac\n+echo >&2 \"* read tree2 and checkout\"\n+$say show_files $tree2\n+\n+if test ! -h path0 && test -d path0 &&\n+   test ! -h path1 && test -d path1 &&\n+   test ! -h path0/file0 && test -f path0/file0 &&\n+   test ! -h path1/file1 && test -f path1/file1\n+then\n+    echo >&2 \"*** ok: checked out correctly.\"\n+else\n+    echo >&2 \"*** bug: did not check out correctly.\"\n+    exit 1\n+fi\n------------------------------------------------\n\n\n"},{"id":"3071","messageId":"20050511221719.GH22686@pasky.ji.cz","threadId":"574","inReplyTo":"7vis1pqvi4.fsf@assigned-by-dhcp.cox.net","subject":"Re: [PATCH] Stop git-rev-list at sha1 match","fromName":"Petr Baudis","fromEmail":"pasky@ucw.cz","sentAt":"2005-05-11T22:17:19Z","receivedAt":"2005-05-11T22:17:19Z","isPatch":true,"sender":{"key":"pasky@ucw.cz","avatar":"https://avatars.githubusercontent.com/u/18439?v=4"},"body":"Dear diary, on Wed, May 11, 2005 at 11:54:11PM CEST, I got a letter\nwhere Junio C Hamano <junkio@cox.net> told me that...\n> >>>>> \"TG\" == Thomas Gleixner <tglx@linutronix.de> writes:\n> \n> TG> You moved the stop behind the printf which is inconsistent to the other\n> TG> stop conditions, but thats a pure cosmetic question as long as it stays\n> TG> that way for ever. \n> \n> While I work on the core GIT changes, I often find myself doing\n> \n>     $ jit-log -l --since linus\n>     $ jit-log -l --since git-jc\n> \n> to see what changes I have in my local work repository, and\n> seeing the branching point (or origin) at the very end of the\n> log made me feel assured that I am not losing anything in the\n> log.  But come to think of it, that is really an unnecessary\n> thing and stopping _before_ the named commit would make more\n> sense.\n> \n> Here is a fixed version.  I am CC'ing pasky hoping he would pick\n> it up.\n\nYes, looks better and more consistent with the rest of the stuff.\n\nBut the very fact that you want this makes me *quite* nervous - I think\nthis is bad thing to do. The problem is, for something like\n\n     o\n     | \\\n     o  |\n     |  o\n     |  o\n     o /\n     o\n    ------\n\nit will show the merged revisions properly, but for\n\n     o\n     | \\\n     o  |\n    ------\n     |  o\n     |  o\n     o /\n     o\n\nit won't show the full merge. Whilst when you do\n\n\t*-log --since foo\n\nI think you mean it to show everything going into the tree since foo -\nthat would include the whole branch you cut off now.\n\nThomas, what are you going to use it for?\n\n> Add --stop-at to git-rev-list command.\n> \n> Signed-off-by: Junio C Hamano <junkio@cox.net>\n\nI liked the previous patch revision commit message much better, I have\nto admit. ;-)\n\n> ---\n> --- a/checkout-cache.c\n> +++ b/checkout-cache.c\n\nI assume this is irrelevant here?\n\n> --- a/rev-list.c\n> +++ b/rev-list.c\n\nLooks ok.\n\nCould you please also update the documentation appropriately? (If we\nhave it, let's keep it up to date.)\n\n> Created: t/t0000.sh (mode:100755)\n> --- /dev/null\n> +++ b/t/t0000.sh\n\nYou want this in too?\n\nStarting to build a testsuite sounds like a good idea, but we should\nprobably first devise some calling convention etc. I personally suck at\nautomated testing.\n\n-- \n\t\t\t\tPetr \"Pasky\" Baudis\nStuff: http://pasky.or.cz/\nC++: an octopus made by nailing extra legs onto a dog. -- Steve Taylor\n"},{"id":"3079","messageId":"1115851742.22180.154.camel@tglx","threadId":"574","inReplyTo":"20050511221719.GH22686@pasky.ji.cz","subject":"Re: [PATCH] Stop git-rev-list at sha1 match","fromName":"Thomas Gleixner","fromEmail":"tglx@linutronix.de","sentAt":"2005-05-11T22:49:02Z","receivedAt":"2005-05-11T22:49:02Z","isPatch":true,"sender":{"key":"tglx@linutronix.de","avatar":null},"body":"On Thu, 2005-05-12 at 00:17 +0200, Petr Baudis wrote:\n> But the very fact that you want this makes me *quite* nervous - I think\n> this is bad thing to do. The problem is, for something like\n> it won't show the full merge. \n> \n> I think you mean it to show everything going into the tree since foo -\n> that would include the whole branch you cut off now.\n\n>From a SCM POV it does not matter.\n\nRn   o\n     | \\\nRn-1 o  |\n     |  o Mn\n     |  o Mn-1\nRn-2 o /\nRn-3 o\n\nIf you are in Repository R, then tracking Rn to Rn-123 gives you a\nlinear result depending on the stop point you chose.\nRn\n---- Stop = Rn-1\nRn-1\n---- Stop = Rn-2\nRn-2\n---- Stop = Rn-3\n\nThe diff between Rn and Rn-1 contains always the changes merged from M\n\n> Thomas, what are you going to use it for?\n\nDisplaing the the changes between commit shaX and shaY :)\n\ntglx\n\n\n"},{"id":"3080","messageId":"20050511225058.GK22686@pasky.ji.cz","threadId":"574","inReplyTo":"1115851742.22180.154.camel@tglx","subject":"Re: [PATCH] Stop git-rev-list at sha1 match","fromName":"Petr Baudis","fromEmail":"pasky@ucw.cz","sentAt":"2005-05-11T22:50:58Z","receivedAt":"2005-05-11T22:50:58Z","isPatch":true,"sender":{"key":"pasky@ucw.cz","avatar":"https://avatars.githubusercontent.com/u/18439?v=4"},"body":"Dear diary, on Thu, May 12, 2005 at 12:49:02AM CEST, I got a letter\nwhere Thomas Gleixner <tglx@linutronix.de> told me that...\n> Rn   o\n>      | \\\n> Rn-1 o  |\n>      |  o Mn\n>      |  o Mn-1\n> Rn-2 o /\n> Rn-3 o\n> \n> If you are in Repository R, then tracking Rn to Rn-123 gives you a\n> linear result depending on the stop point you chose.\n> Rn\n> ---- Stop = Rn-1\n> Rn-1\n> ---- Stop = Rn-2\n\nMn\nMn-1\n\n> Rn-2\n> ---- Stop = Rn-3\n> \n> The diff between Rn and Rn-1 contains always the changes merged from M\n\nYes, but you get the merge commits again since rev-list follows all the\nparents.\n\n-- \n\t\t\t\tPetr \"Pasky\" Baudis\nStuff: http://pasky.or.cz/\nC++: an octopus made by nailing extra legs onto a dog. -- Steve Taylor\n"},{"id":"3082","messageId":"1115852914.22180.170.camel@tglx","threadId":"574","inReplyTo":"20050511225058.GK22686@pasky.ji.cz","subject":"Re: [PATCH] Stop git-rev-list at sha1 match","fromName":"Thomas Gleixner","fromEmail":"tglx@linutronix.de","sentAt":"2005-05-11T23:08:34Z","receivedAt":"2005-05-11T23:08:34Z","isPatch":true,"sender":{"key":"tglx@linutronix.de","avatar":null},"body":"On Thu, 2005-05-12 at 00:50 +0200, Petr Baudis wrote:\n> > Rn\n> > ---- Stop = Rn-1\n> > Rn-1\n> > ---- Stop = Rn-2\n> \n> Mn\n> Mn-1\n> \n> > Rn-2\n> > ---- Stop = Rn-3\n> > \n> > The diff between Rn and Rn-1 contains always the changes merged from M\n> \n> Yes, but you get the merge commits again since rev-list follows all the\n> parents.\n\nThat's plain wrong. The Mn(1) change hit repository r between revision\nRn and Rn-1 and nowhere else. \n\nDate is irrelevant. The only relevant thing is the parent child(s)\nrelationship.\n\nWhat you get doing this is history cluttering. In the repository R it is\ncompletely irrelevant when Mn resp. Mn-1 was created. The only relevant\npoint is when it was merged into repository R.\n\nBitkeeper does the same bogus thing to make changesets appear in a\nlinear order. Look at the changeset logs. If you diff the versions\nexported by bitkeeper then you get complete nonsense. \n\nPlease do not make the same mistake. \n\n\ntglx\n\n\n\n\n\n"},{"id":"3088","messageId":"20050511234455.GL22686@pasky.ji.cz","threadId":"574","inReplyTo":"1115852914.22180.170.camel@tglx","subject":"Re: [PATCH] Stop git-rev-list at sha1 match","fromName":"Petr Baudis","fromEmail":"pasky@ucw.cz","sentAt":"2005-05-11T23:44:55Z","receivedAt":"2005-05-11T23:44:55Z","isPatch":true,"sender":{"key":"pasky@ucw.cz","avatar":"https://avatars.githubusercontent.com/u/18439?v=4"},"body":"Dear diary, on Thu, May 12, 2005 at 01:08:34AM CEST, I got a letter\nwhere Thomas Gleixner <tglx@linutronix.de> told me that...\n> On Thu, 2005-05-12 at 00:50 +0200, Petr Baudis wrote:\n> > > Rn\n> > > ---- Stop = Rn-1\n> > > Rn-1\n> > > ---- Stop = Rn-2\n> > \n> > Mn\n> > Mn-1\n> > \n> > > Rn-2\n> > > ---- Stop = Rn-3\n> > > \n> > > The diff between Rn and Rn-1 contains always the changes merged from M\n> > \n> > Yes, but you get the merge commits again since rev-list follows all the\n> > parents.\n> \n> That's plain wrong. The Mn(1) change hit repository r between revision\n> Rn and Rn-1 and nowhere else. \n> \n> Date is irrelevant. The only relevant thing is the parent child(s)\n> relationship.\n\nWhat I described is just how rev-list works (now), nothing more. This is\nwhat you get when you use rev-list.\n\nPlease see the thread of\n\n5730     Apr 27 H. Peter Anvin  ( 0.2K) kernel.org now has gitweb installed\n\nfor extensive discussion on how (it is impossible or very hard) to do\nbetter.\n\nSo how would you order the list of commits?\n\n-- \n\t\t\t\tPetr \"Pasky\" Baudis\nStuff: http://pasky.or.cz/\nC++: an octopus made by nailing extra legs onto a dog. -- Steve Taylor\n"},{"id":"3095","messageId":"1115857873.22180.253.camel@tglx","threadId":"574","inReplyTo":"20050511234455.GL22686@pasky.ji.cz","subject":"Re: [PATCH] Stop git-rev-list at sha1 match","fromName":"Thomas Gleixner","fromEmail":"tglx@linutronix.de","sentAt":"2005-05-12T00:31:13Z","receivedAt":"2005-05-12T00:31:13Z","isPatch":true,"sender":{"key":"tglx@linutronix.de","avatar":null},"body":"On Thu, 2005-05-12 at 01:44 +0200, Petr Baudis wrote:\n> for extensive discussion on how (it is impossible or very hard) to do\n> better.\n\n:)\n\n> So how would you order the list of commits?\n\nRn\n  merged Mn\n  merged Mn-1\nRn-1\n....\n\nThat's the relevant information in repository R. Looking at it from\nrepository M after M updated to Rn\n\n(Mn+1) == Rn\t; Mn+1 is not created due to head forward\n  merged Rn\n  .. \n  merged Rn-3\nMn\nMn-1\n\nThats the historical correct ordering from a repository point of view.\nThats the only relevant information IMNSHO.\n\nThe dates of author and committer are retrievable in each repository,\nbut the order of commits are not.\n\n\ntglx\n\n\n\n"},{"id":"3106","messageId":"7v4qd9mcp1.fsf@assigned-by-dhcp.cox.net","threadId":"574","inReplyTo":"20050511221719.GH22686@pasky.ji.cz","subject":"Re: [PATCH] Stop git-rev-list at sha1 match","fromName":"Junio C Hamano","fromEmail":"junkio@cox.net","sentAt":"2005-05-12T01:54:02Z","receivedAt":"2005-05-12T01:54:02Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":">>>>> \"PB\" == Petr Baudis <pasky@ucw.cz> writes:\n\nPB> it will show the merged revisions properly, but for\n\nPB>      o\nPB>      | \\\nPB>      o  |\nPB>     ------\nPB>      |  o\nPB>      |  o\nPB>      o /\nPB>      o\n\nPB> it won't show the full merge. Whilst when you do\n\nPB> \t*-log --since foo\n\nPB> I think you mean it to show everything going into the tree since foo -\nPB> that would include the whole branch you cut off now.\n\nI use \"rev-tree HEAD ^$(git-merge-base HEAD foo)\" for this\nkind of thing, so rev-list does not really matter.\n\n>> --- a/checkout-cache.c\n>> +++ b/checkout-cache.c\nPB> I assume this is irrelevant here?\n\nSorry for sending a dirty patch in.  Will fix it up.\n\n\n"},{"id":"3107","messageId":"7vy8alkxbf.fsf@assigned-by-dhcp.cox.net","threadId":"574","inReplyTo":"7v4qd9mcp1.fsf@assigned-by-dhcp.cox.net","subject":"Re: [PATCH] Stop git-rev-list at sha1 match","fromName":"Junio C Hamano","fromEmail":"junkio@cox.net","sentAt":"2005-05-12T02:11:32Z","receivedAt":"2005-05-12T02:11:32Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":">>>>> \"JCH\" == Junio C Hamano <junkio@cox.net> writes:\n>>>>> \"PB\" == Petr Baudis <pasky@ucw.cz> writes:\n\n>>> --- a/checkout-cache.c\n>>> +++ b/checkout-cache.c\nPB> I assume this is irrelevant here?\nJCH> Sorry for sending a dirty patch in.  Will fix it up.\n\n------------\nIntroduce \"rev-list --stop-at=<commit>\".\n\nAdditional option, --stop-at=<commit>, is introduced.  The\ngit-rev-list output stops just before showing the named commit.\n\nThis is based on Thoms Gleixner's patch but slightly reworked,\nwith documentation updates.\n\nSigned-off-by: Junio C Hamano <junkio@cox.net>\n---\n\nDocumentation/git-rev-list.txt |   18 +++++++++++++++++-\nrev-list.c                     |   20 ++++++++++++++++----\n2 files changed, 33 insertions(+), 5 deletions(-)\n\n--- a/Documentation/git-rev-list.txt\n+++ b/Documentation/git-rev-list.txt\n@@ -9,7 +9,10 @@\n \n SYNOPSIS\n --------\n-'git-rev-list' <commit>\n+'git-rev-list'\t[--max-count=<number>]\n+\t\t[--max-age=<unixtime>]\n+\t\t[--min-age=<unixtime>]\n+\t\t[--stop-at=<commit>] <commit>\n \n DESCRIPTION\n -----------\n@@ -17,6 +20,19 @@\n given commit, taking ancestry relationship into account.  This is\n useful to produce human-readable log output.\n \n+OPTIONS\n+-------\n+--max-count=<number>::\n+\tStop after showing <number> commits.\n+\n+--max-age=<unixtime>::\n+\tStop after showing commit made before <unixtime>.\n+\n+--min-age=<unixtime>::\n+\tSkip until commit made before <unixtime>.\n+\n+--stop-at=<commit>::\n+\tStop just before showing <commit>.\n \n Author\n ------\n--- a/rev-list.c\n+++ b/rev-list.c\n@@ -1,12 +1,21 @@\n #include \"cache.h\"\n #include \"commit.h\"\n \n+static const char *rev_list_usage = \n+\"usage: rev-list [OPTION] commit-id\\n\"\n+\"  --max-count=nr\\n\"\n+\"  --max-age=epoch\\n\"\n+\"  --min-age=epoch\\n\"\n+\"  --stop-at=commit\\n\";\n+\n int main(int argc, char **argv)\n {\n \tunsigned char sha1[20];\n \tstruct commit_list *list = NULL;\n \tstruct commit *commit;\n \tchar *commit_arg = NULL;\n+\tunsigned char stop_at[20];\n+\tint has_stop_at = 0;\n \tint i;\n \tunsigned long max_age = -1;\n \tunsigned long min_age = -1;\n@@ -21,16 +30,17 @@\n \t\t\tmax_age = atoi(arg + 10);\n \t\t} else if (!strncmp(arg, \"--min-age=\", 10)) {\n \t\t\tmin_age = atoi(arg + 10);\n+\t\t} else if (!strncmp(arg, \"--stop-at=\", 10)) {\n+\t\t\tif (get_sha1(arg + 10, stop_at))\n+\t\t\t\tusage(rev_list_usage);\n+\t\t\thas_stop_at = 1;\n \t\t} else {\n \t\t\tcommit_arg = arg;\n \t\t}\n \t}\n \n \tif (!commit_arg || get_sha1(commit_arg, sha1))\n-\t\tusage(\"usage: rev-list [OPTION] commit-id\\n\"\n-\t\t      \"  --max-count=nr\\n\"\n-\t\t      \"  --max-age=epoch\\n\"\n-\t\t      \"  --min-age=epoch\\n\");\n+\t\tusage(rev_list_usage);\n \n \tcommit = lookup_commit(sha1);\n \tif (!commit || parse_commit(commit) < 0)\n@@ -46,6 +56,8 @@\n \t\t\tbreak;\n \t\tif (max_count != -1 && !max_count--)\n \t\t\tbreak;\n+\t\tif (has_stop_at && !memcmp(stop_at, commit->object.sha1, 20))\n+\t\t\tbreak;\n \t\tprintf(\"%s\\n\", sha1_to_hex(commit->object.sha1));\n \t} while (list);\n \treturn 0;\n------------------------------------------------\n\n"},{"id":"3226","messageId":"20050513052633.GA16464@pasky.ji.cz","threadId":"574","inReplyTo":"1115857873.22180.253.camel@tglx","subject":"Re: [PATCH] Stop git-rev-list at sha1 match","fromName":"Petr Baudis","fromEmail":"pasky@ucw.cz","sentAt":"2005-05-13T05:26:33Z","receivedAt":"2005-05-13T05:26:33Z","isPatch":true,"sender":{"key":"pasky@ucw.cz","avatar":"https://avatars.githubusercontent.com/u/18439?v=4"},"body":"Dear diary, on Thu, May 12, 2005 at 02:31:13AM CEST, I got a letter\nwhere Thomas Gleixner <tglx@linutronix.de> told me that...\n> On Thu, 2005-05-12 at 01:44 +0200, Petr Baudis wrote:\n> > for extensive discussion on how (it is impossible or very hard) to do\n> > better.\n> \n> :)\n> \n> > So how would you order the list of commits?\n> \n> Rn\n>   merged Mn\n>   merged Mn-1\n> Rn-1\n> ....\n> \n> That's the relevant information in repository R. Looking at it from\n> repository M after M updated to Rn\n> \n> (Mn+1) == Rn\t; Mn+1 is not created due to head forward\n>   merged Rn\n>   .. \n>   merged Rn-3\n> Mn\n> Mn-1\n> \n> Thats the historical correct ordering from a repository point of view.\n> Thats the only relevant information IMNSHO.\n\nBut it is impossible to reconstruct without the repoid or something. So\nmy point that it makes no sense and is actually dangerous with the\ncurrent rev-list output order holds.\n\n-- \n\t\t\t\tPetr \"Pasky\" Baudis\nStuff: http://pasky.or.cz/\nC++: an octopus made by nailing extra legs onto a dog. -- Steve Taylor\n"}]}