From 4e2e5647f23e2babcb188fd05eececbb261e2f17 Mon Sep 17 00:00:00 2001 From: "Aneesh Kumar K.V" Date: Sun, 4 Jun 2006 23:37:48 +0530 Subject: [PATCH 01/10] gitview: Add some useful keybindings. Signed-off-by: Junio C Hamano --- contrib/gitview/gitview | 15 +++++++++++++++ contrib/gitview/gitview.txt | 6 ++++++ 2 files changed, 21 insertions(+) diff --git a/contrib/gitview/gitview b/contrib/gitview/gitview index b836047cf3..3b6bdceeeb 100755 --- a/contrib/gitview/gitview +++ b/contrib/gitview/gitview @@ -450,6 +450,9 @@ class GitView: self.accel_group = gtk.AccelGroup() self.window.add_accel_group(self.accel_group) self.accel_group.connect_group(0xffc2, 0, gtk.ACCEL_LOCKED, self.refresh); + self.accel_group.connect_group(0xffc1, 0, gtk.ACCEL_LOCKED, self.maximize); + self.accel_group.connect_group(0xffc8, 0, gtk.ACCEL_LOCKED, self.fullscreen); + self.accel_group.connect_group(0xffc9, 0, gtk.ACCEL_LOCKED, self.unfullscreen); self.window.add(self.construct()) @@ -461,6 +464,18 @@ class GitView: self.window.show() return True + def maximize(self, widget, event=None, *arguments, **keywords): + self.window.maximize() + return True + + def fullscreen(self, widget, event=None, *arguments, **keywords): + self.window.fullscreen() + return True + + def unfullscreen(self, widget, event=None, *arguments, **keywords): + self.window.unfullscreen() + return True + def get_bt_sha1(self): """ Update the bt_sha1 dictionary with the respective sha1 details """ diff --git a/contrib/gitview/gitview.txt b/contrib/gitview/gitview.txt index e3bc4f46c2..6924df286e 100644 --- a/contrib/gitview/gitview.txt +++ b/contrib/gitview/gitview.txt @@ -26,8 +26,14 @@ OPTIONS All the valid option for git-rev-list(1) Key Bindings: + F4: + To maximize the window F5: To reread references. + F11: + Full screen + F12: + Leave full screen EXAMPLES ------ From eff97e3faeb28f6521851c1b3be1a54a2138f12a Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Sun, 4 Jun 2006 10:48:31 -0700 Subject: [PATCH 02/10] read-tree: fix eye-candy. Anton Blanchard spotted that watching checkout stage of a clone on a slow terminal takes ages because it forgot to clear the "once a second happened" flag, so instead of updates the percentage output for every file it checks out after the first second has passed. Signed-off-by: Linus Torvalds Signed-off-by: Junio C Hamano --- builtin-read-tree.c | 1 + 1 file changed, 1 insertion(+) diff --git a/builtin-read-tree.c b/builtin-read-tree.c index 085e11e7c4..8d1a22d373 100644 --- a/builtin-read-tree.c +++ b/builtin-read-tree.c @@ -376,6 +376,7 @@ static void check_updates(struct cache_entry **src, int nr) fprintf(stderr, "%4u%% (%u/%u) done\r", percent, cnt, total); last_percent = percent; + progress_update = 0; } } } From c51901de1dfd0670e3394157c2909f5036be3ea7 Mon Sep 17 00:00:00 2001 From: "Horst H. von Brand" Date: Sun, 4 Jun 2006 19:53:45 -0400 Subject: [PATCH 03/10] Add example xinetd(8) configuration to Documentation/everyday.txt Many Linux distributions use xinetd(8), not inetd(8). Give a sample configuration file. Signed-off-by: Horst H. von Brand Signed-off-by: Junio C Hamano --- Documentation/everyday.txt | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/Documentation/everyday.txt b/Documentation/everyday.txt index 2ad2d61300..7a04f46038 100644 --- a/Documentation/everyday.txt +++ b/Documentation/everyday.txt @@ -377,6 +377,29 @@ git stream tcp nowait nobody \ + The actual configuration line should be on one line. +Run git-daemon to serve /pub/scm from xinetd.:: ++ +------------ +$ cat /etc/xinetd.d/git-daemon +# default: off +# description: The git server offers access to git repositories +service git +{ + disable = no + type = UNLISTED + port = 9418 + socket_type = stream + wait = no + user = nobody + server = /usr/bin/git-daemon + server_args = --inetd --syslog --export-all --base-path=/pub/scm + log_on_failure += USERID +} +------------ ++ +Check your xinetd(8) documentation and setup, this is from a Fedora system. +Others might be different. + Give push/pull only access to developers.:: + ------------ From 53bcf78a023cee565a31c2956d13dba652f9ccf3 Mon Sep 17 00:00:00 2001 From: "Horst H. von Brand" Date: Sun, 4 Jun 2006 22:10:33 -0400 Subject: [PATCH 04/10] Fix Documentation/everyday.txt: Junio's workflow The workflow for Junio was badly formatted. Signed-off-by: Horst H. von Brand Signed-off-by: Junio C Hamano --- Documentation/everyday.txt | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/Documentation/everyday.txt b/Documentation/everyday.txt index 7a04f46038..6745ab5fc5 100644 --- a/Documentation/everyday.txt +++ b/Documentation/everyday.txt @@ -336,15 +336,20 @@ master, nor exposed as a part of a stable branch. <11> make sure I did not accidentally rewind master beyond what I already pushed out. "ko" shorthand points at the repository I have at kernel.org, and looks like this: - $ cat .git/remotes/ko - URL: kernel.org:/pub/scm/git/git.git - Pull: master:refs/tags/ko-master - Pull: maint:refs/tags/ko-maint - Push: master - Push: +pu - Push: maint ++ +------------ +$ cat .git/remotes/ko +URL: kernel.org:/pub/scm/git/git.git +Pull: master:refs/tags/ko-master +Pull: maint:refs/tags/ko-maint +Push: master +Push: +pu +Push: maint +------------ ++ In the output from "git show-branch", "master" should have everything "ko-master" has. + <12> push out the bleeding edge. <13> push the tag out, too. From 2befe6feb99da9fb73b9e8c218b414419ef947ec Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Mon, 5 Jun 2006 12:47:49 -0700 Subject: [PATCH 05/10] Fix typo in tutorial-2.txt This should be obvious enough. I didn't actually _test_ the tutorial, but if the old command worked, something is really wrong! Signed-off-by: Linus "Duh!" Torvalds Signed-off-by: Junio C Hamano --- Documentation/tutorial-2.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/tutorial-2.txt b/Documentation/tutorial-2.txt index 82c692254e..894ca5e06f 100644 --- a/Documentation/tutorial-2.txt +++ b/Documentation/tutorial-2.txt @@ -136,7 +136,7 @@ The "tree" object here refers to the new state of the tree: ------------------------------------------------ $ git ls-tree d0492b36 100644 blob a0423896973644771497bdc03eb99d5281615b51 file.txt -$ git cat-file commit a0423896 +$ git cat-file blob a0423896 hello world! ------------------------------------------------ From 87cefaaff958e30204a21757012a46883175c00f Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Mon, 5 Jun 2006 11:44:36 -0700 Subject: [PATCH 06/10] rev-list: fix process_tree() conversion. The tree-walking conversion of the "process_tree()" function broke packing by using an unrelated variable from outer scope. Signed-off-by: Junio C Hamano --- builtin-rev-list.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/builtin-rev-list.c b/builtin-rev-list.c index 17c04b962d..e885624255 100644 --- a/builtin-rev-list.c +++ b/builtin-rev-list.c @@ -135,9 +135,9 @@ static struct object_list **process_tree(struct tree *tree, while (tree_entry(&desc, &entry)) { if (S_ISDIR(entry.mode)) - p = process_tree(lookup_tree(entry.sha1), p, &me, name); + p = process_tree(lookup_tree(entry.sha1), p, &me, entry.path); else - p = process_blob(lookup_blob(entry.sha1), p, &me, name); + p = process_blob(lookup_blob(entry.sha1), p, &me, entry.path); } free(tree->buffer); tree->buffer = NULL; From ce0bd64299ae148ef61a63edcac635de41254cb5 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Mon, 5 Jun 2006 12:03:31 -0700 Subject: [PATCH 07/10] pack-objects: improve path grouping heuristics. This trivial patch not only simplifies the name hashing, it actually improves packing for both git and the kernel. The git archive pack shrinks from 6824090->6622627 bytes (a 3% improvement), and the kernel pack shrinks from 108756213 to 108219021 (a mere 0.5% improvement, but still, it's an improvement from making the hashing much simpler!) We just create a 32-bit hash, where we "age" previous characters by two bits, so the last characters in a filename count most. So when we then compare the hashes in the sort routine, filenames that end the same way sort the same way. It takes the subdirectory into account (unless the filename is > 16 characters), but files with the same name within the same subdirectory will obviously sort closer than files in different subdirectories. And, incidentally (which is why I tried the hash change in the first place, of course) builtin-rev-list.c will sort fairly close to rev-list.c. And no, it's not a "good hash" in the sense of being secure or unique, but that's not what we're looking for. The whole "hash" thing is misnamed here. It's not so much a hash as a "sorting number". [jc: rolled in simplification for computing the sorting number computation for thin pack base objects] Signed-off-by: Linus Torvalds Signed-off-by: Junio C Hamano --- pack-objects.c | 69 ++++++++++++++------------------------------------ 1 file changed, 19 insertions(+), 50 deletions(-) diff --git a/pack-objects.c b/pack-objects.c index 3590cd5e59..179560f2bd 100644 --- a/pack-objects.c +++ b/pack-objects.c @@ -463,48 +463,21 @@ static void rehash_objects(void) } } -struct name_path { - struct name_path *up; - const char *elem; - int len; -}; - -#define DIRBITS 12 - -static unsigned name_hash(struct name_path *path, const char *name) +static unsigned name_hash(const char *name) { - struct name_path *p = path; - const char *n = name + strlen(name); - unsigned hash = 0, name_hash = 0, name_done = 0; - - if (n != name && n[-1] == '\n') - n--; - while (name <= --n) { - unsigned char c = *n; - if (c == '/' && !name_done) { - name_hash = hash; - name_done = 1; - hash = 0; - } - hash = hash * 11 + c; - } - if (!name_done) { - name_hash = hash; - hash = 0; - } - for (p = path; p; p = p->up) { - hash = hash * 11 + '/'; - n = p->elem + p->len; - while (p->elem <= --n) { - unsigned char c = *n; - hash = hash * 11 + c; - } - } + unsigned char c; + unsigned hash = 0; + /* - * Make sure "Makefile" and "t/Makefile" are hashed separately - * but close enough. + * This effectively just creates a sortable number from the + * last sixteen non-whitespace characters. Last characters + * count "most", so things that end in ".c" sort together. */ - hash = (name_hash<> 2) + (c << 24); + } return hash; } @@ -686,9 +659,9 @@ static int name_cmp_len(const char *name) } static void add_pbase_object(struct tree_desc *tree, - struct name_path *up, const char *name, - int cmplen) + int cmplen, + const char *fullname) { struct name_entry entry; @@ -702,13 +675,12 @@ static void add_pbase_object(struct tree_desc *tree, sha1_object_info(entry.sha1, type, &size)) continue; if (name[cmplen] != '/') { - unsigned hash = name_hash(up, name); + unsigned hash = name_hash(fullname); add_object_entry(entry.sha1, hash, 1); return; } if (!strcmp(type, tree_type)) { struct tree_desc sub; - struct name_path me; struct pbase_tree_cache *tree; const char *down = name+cmplen+1; int downlen = name_cmp_len(down); @@ -719,10 +691,7 @@ static void add_pbase_object(struct tree_desc *tree, sub.buf = tree->tree_data; sub.size = tree->tree_size; - me.up = up; - me.elem = entry.path; - me.len = entry.pathlen; - add_pbase_object(&sub, &me, down, downlen); + add_pbase_object(&sub, down, downlen, fullname); pbase_tree_put(tree); } } @@ -778,14 +747,14 @@ static void add_preferred_base_object(char *name, unsigned hash) for (it = pbase_tree; it; it = it->next) { if (cmplen == 0) { - hash = name_hash(NULL, ""); + hash = name_hash(""); add_object_entry(it->pcache.sha1, hash, 1); } else { struct tree_desc tree; tree.buf = it->pcache.tree_data; tree.size = it->pcache.tree_size; - add_pbase_object(&tree, NULL, name, cmplen); + add_pbase_object(&tree, name, cmplen, name); } } } @@ -1328,7 +1297,7 @@ int main(int argc, char **argv) } if (get_sha1_hex(line, sha1)) die("expected sha1, got garbage:\n %s", line); - hash = name_hash(NULL, line+41); + hash = name_hash(line+41); add_preferred_base_object(line+41, hash); add_object_entry(sha1, hash, 0); } From 441c823e892ba7408e87d26b6e77def5975c1c60 Mon Sep 17 00:00:00 2001 From: Nick Hengeveld Date: Mon, 5 Jun 2006 13:02:29 -0700 Subject: [PATCH 08/10] builtin-push: don't pass --thin to HTTP transport git-http-push does not currently use packs to transfer objects. Signed-off-by: Nick Hengeveld Signed-off-by: Junio C Hamano --- builtin-push.c | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/builtin-push.c b/builtin-push.c index e530022824..66b9407822 100644 --- a/builtin-push.c +++ b/builtin-push.c @@ -214,7 +214,7 @@ static int do_push(const char *repo) { const char *uri[MAX_URI]; int i, n; - int remote; + int common_argc; const char **argv; int argc; @@ -231,23 +231,25 @@ static int do_push(const char *repo) argv[argc++] = "--force"; if (execute) argv[argc++] = execute; - if (thin) - argv[argc++] = "--thin"; - remote = argc; - argv[argc++] = "dummy-remote"; - while (refspec_nr--) - argv[argc++] = *refspec++; - argv[argc] = NULL; + common_argc = argc; for (i = 0; i < n; i++) { int error; + int dest_argc = common_argc; + int dest_refspec_nr = refspec_nr; + const char **dest_refspec = refspec; const char *dest = uri[i]; const char *sender = "git-send-pack"; if (!strncmp(dest, "http://", 7) || !strncmp(dest, "https://", 8)) sender = "git-http-push"; + else if (thin) + argv[dest_argc++] = "--thin"; argv[0] = sender; - argv[remote] = dest; + argv[dest_argc++] = dest; + while (dest_refspec_nr--) + argv[dest_argc++] = *dest_refspec++; + argv[dest_argc] = NULL; error = run_command_v(argc, argv); if (!error) continue; From 2b11e3170e919866c7f5554dd4089289a1bb6726 Mon Sep 17 00:00:00 2001 From: Johannes Schindelin Date: Mon, 5 Jun 2006 19:43:52 +0200 Subject: [PATCH 09/10] If you have a config containing something like this: [alias] l = "log --stat -M ORIG_HEAD.." you can call git l and it will do the same as git log --stat -M ORIG_HEAD.. Signed-off-by: Johannes Schindelin Signed-off-by: Junio C Hamano --- git.c | 111 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 111 insertions(+) diff --git a/git.c b/git.c index bc463c98ea..8854472453 100644 --- a/git.c +++ b/git.c @@ -10,6 +10,7 @@ #include #include "git-compat-util.h" #include "exec_cmd.h" +#include "cache.h" #include "builtin.h" @@ -32,6 +33,113 @@ static void prepend_to_path(const char *dir, int len) setenv("PATH", path, 1); } +static const char *alias_command; +static char *alias_string = NULL; + +static int git_alias_config(const char *var, const char *value) +{ + if (!strncmp(var, "alias.", 6) && !strcmp(var + 6, alias_command)) { + alias_string = strdup(value); + } + return 0; +} + +static int split_cmdline(char *cmdline, const char ***argv) +{ + int src, dst, count = 0, size = 16; + char quoted = 0; + + *argv = malloc(sizeof(char*) * size); + + /* split alias_string */ + (*argv)[count++] = cmdline; + for (src = dst = 0; cmdline[src];) { + char c = cmdline[src]; + if (!quoted && isspace(c)) { + cmdline[dst++] = 0; + while (cmdline[++src] + && isspace(cmdline[src])) + ; /* skip */ + if (count >= size) { + size += 16; + *argv = realloc(*argv, sizeof(char*) * size); + } + (*argv)[count++] = cmdline + dst; + } else if(!quoted && (c == '\'' || c == '"')) { + quoted = c; + src++; + } else if (c == quoted) { + quoted = 0; + src++; + } else { + if (c == '\\' && quoted != '\'') { + src++; + c = cmdline[src]; + if (!c) { + free(*argv); + *argv = NULL; + return error("cmdline ends with \\"); + } + } + cmdline[dst++] = c; + src++; + } + } + + cmdline[dst] = 0; + + if (quoted) { + free(*argv); + *argv = NULL; + return error("unclosed quote"); + } + + return count; +} + +static int handle_alias(int *argcp, const char ***argv) +{ + int nongit = 0, ret = 0; + const char *subdir; + + subdir = setup_git_directory_gently(&nongit); + if (!nongit) { + int count; + const char** new_argv; + + alias_command = (*argv)[0]; + git_config(git_alias_config); + if (alias_string) { + + count = split_cmdline(alias_string, &new_argv); + + if (count < 1) + die("empty alias for %s", alias_command); + + if (!strcmp(alias_command, new_argv[0])) + die("recursive alias: %s", alias_command); + + /* insert after command name */ + if (*argcp > 1) { + new_argv = realloc(new_argv, sizeof(char*) * + (count + *argcp - 1)); + memcpy(new_argv + count, *argv, sizeof(char*) * + (*argcp - 1)); + } + + *argv = new_argv; + *argcp += count - 1; + + ret = 1; + } + } + + if (subdir) + chdir(subdir); + + return ret; +} + const char git_version_string[] = GIT_VERSION; static void handle_internal_command(int argc, const char **argv, char **envp) @@ -121,6 +229,7 @@ int main(int argc, const char **argv, char **envp) if (!strncmp(cmd, "git-", 4)) { cmd += 4; argv[0] = cmd; + handle_alias(&argc, &argv); handle_internal_command(argc, argv, envp); die("cannot handle %s internally", cmd); } @@ -178,6 +287,8 @@ int main(int argc, const char **argv, char **envp) exec_path = git_exec_path(); prepend_to_path(exec_path, strlen(exec_path)); + handle_alias(&argc, &argv); + /* See if it's an internal command */ handle_internal_command(argc, argv, envp); From a025463bc0ec2c894a88f2dfb44cf88ba71bb712 Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Mon, 5 Jun 2006 18:09:40 -0700 Subject: [PATCH 10/10] git alias: try alias last. This disables alias "foo" from being used for git-foo, and when we do use alias we check the built-in and then existing command names first and then alias as the fallback. This avoids the problem of common commands used in scripts getting clobbered by user specific aliases. Signed-off-by: Junio C Hamano --- git.c | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/git.c b/git.c index 8854472453..6db8f2bc23 100644 --- a/git.c +++ b/git.c @@ -202,6 +202,7 @@ int main(int argc, const char **argv, char **envp) char *slash = strrchr(cmd, '/'); char git_command[PATH_MAX + 1]; const char *exec_path = NULL; + int done_alias = 0; /* * Take the basename of argv[0] as the command @@ -229,7 +230,6 @@ int main(int argc, const char **argv, char **envp) if (!strncmp(cmd, "git-", 4)) { cmd += 4; argv[0] = cmd; - handle_alias(&argc, &argv); handle_internal_command(argc, argv, envp); die("cannot handle %s internally", cmd); } @@ -287,13 +287,21 @@ int main(int argc, const char **argv, char **envp) exec_path = git_exec_path(); prepend_to_path(exec_path, strlen(exec_path)); - handle_alias(&argc, &argv); + while (1) { + /* See if it's an internal command */ + handle_internal_command(argc, argv, envp); - /* See if it's an internal command */ - handle_internal_command(argc, argv, envp); + /* .. then try the external ones */ + execv_git_cmd(argv); - /* .. then try the external ones */ - execv_git_cmd(argv); + /* It could be an alias -- this works around the insanity + * of overriding "git log" with "git show" by having + * alias.log = show + */ + if (done_alias || !handle_alias(&argc, &argv)) + break; + done_alias = 1; + } if (errno == ENOENT) cmd_usage(0, exec_path, "'%s' is not a git-command", cmd);