Merge branch 'js/alias' into next

* js/alias:
  git alias: try alias last.
  If you have a config containing something like this:
  builtin-push: don't pass --thin to HTTP transport
  pack-objects: improve path grouping heuristics.
  rev-list: fix process_tree() conversion.
  Fix typo in tutorial-2.txt
  Fix Documentation/everyday.txt: Junio's workflow
  Add example xinetd(8) configuration to Documentation/everyday.txt
  read-tree: fix eye-candy.
  gitview: Add some useful keybindings.
This commit is contained in:
Junio C Hamano 2006-06-05 18:10:20 -07:00
commit c49b5a3c89
9 changed files with 212 additions and 72 deletions

View File

@ -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 <11> make sure I did not accidentally rewind master beyond what I
already pushed out. "ko" shorthand points at the repository I have already pushed out. "ko" shorthand points at the repository I have
at kernel.org, and looks like this: 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 $ cat .git/remotes/ko
Pull: maint:refs/tags/ko-maint URL: kernel.org:/pub/scm/git/git.git
Push: master Pull: master:refs/tags/ko-master
Push: +pu Pull: maint:refs/tags/ko-maint
Push: maint Push: master
Push: +pu
Push: maint
------------
+
In the output from "git show-branch", "master" should have In the output from "git show-branch", "master" should have
everything "ko-master" has. everything "ko-master" has.
<12> push out the bleeding edge. <12> push out the bleeding edge.
<13> push the tag out, too. <13> push the tag out, too.
@ -377,6 +382,29 @@ git stream tcp nowait nobody \
+ +
The actual configuration line should be on one line. 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.:: Give push/pull only access to developers.::
+ +
------------ ------------

View File

@ -136,7 +136,7 @@ The "tree" object here refers to the new state of the tree:
------------------------------------------------ ------------------------------------------------
$ git ls-tree d0492b36 $ git ls-tree d0492b36
100644 blob a0423896973644771497bdc03eb99d5281615b51 file.txt 100644 blob a0423896973644771497bdc03eb99d5281615b51 file.txt
$ git cat-file commit a0423896 $ git cat-file blob a0423896
hello world! hello world!
------------------------------------------------ ------------------------------------------------

View File

@ -214,7 +214,7 @@ static int do_push(const char *repo)
{ {
const char *uri[MAX_URI]; const char *uri[MAX_URI];
int i, n; int i, n;
int remote; int common_argc;
const char **argv; const char **argv;
int argc; int argc;
@ -231,23 +231,25 @@ static int do_push(const char *repo)
argv[argc++] = "--force"; argv[argc++] = "--force";
if (execute) if (execute)
argv[argc++] = execute; argv[argc++] = execute;
if (thin) common_argc = argc;
argv[argc++] = "--thin";
remote = argc;
argv[argc++] = "dummy-remote";
while (refspec_nr--)
argv[argc++] = *refspec++;
argv[argc] = NULL;
for (i = 0; i < n; i++) { for (i = 0; i < n; i++) {
int error; 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 *dest = uri[i];
const char *sender = "git-send-pack"; const char *sender = "git-send-pack";
if (!strncmp(dest, "http://", 7) || if (!strncmp(dest, "http://", 7) ||
!strncmp(dest, "https://", 8)) !strncmp(dest, "https://", 8))
sender = "git-http-push"; sender = "git-http-push";
else if (thin)
argv[dest_argc++] = "--thin";
argv[0] = sender; 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); error = run_command_v(argc, argv);
if (!error) if (!error)
continue; continue;

View File

@ -377,6 +377,7 @@ static void check_updates(struct cache_entry **src, int nr)
fprintf(stderr, "%4u%% (%u/%u) done\r", fprintf(stderr, "%4u%% (%u/%u) done\r",
percent, cnt, total); percent, cnt, total);
last_percent = percent; last_percent = percent;
progress_update = 0;
} }
} }
} }

View File

@ -135,9 +135,9 @@ static struct object_list **process_tree(struct tree *tree,
while (tree_entry(&desc, &entry)) { while (tree_entry(&desc, &entry)) {
if (S_ISDIR(entry.mode)) 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 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); free(tree->buffer);
tree->buffer = NULL; tree->buffer = NULL;

View File

@ -450,6 +450,9 @@ class GitView:
self.accel_group = gtk.AccelGroup() self.accel_group = gtk.AccelGroup()
self.window.add_accel_group(self.accel_group) 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(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()) self.window.add(self.construct())
@ -461,6 +464,18 @@ class GitView:
self.window.show() self.window.show()
return True 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): def get_bt_sha1(self):
""" Update the bt_sha1 dictionary with the """ Update the bt_sha1 dictionary with the
respective sha1 details """ respective sha1 details """

View File

@ -26,8 +26,14 @@ OPTIONS
<args> <args>
All the valid option for git-rev-list(1) All the valid option for git-rev-list(1)
Key Bindings: Key Bindings:
F4:
To maximize the window
F5: F5:
To reread references. To reread references.
F11:
Full screen
F12:
Leave full screen
EXAMPLES EXAMPLES
------ ------

127
git.c
View File

@ -10,6 +10,7 @@
#include <stdarg.h> #include <stdarg.h>
#include "git-compat-util.h" #include "git-compat-util.h"
#include "exec_cmd.h" #include "exec_cmd.h"
#include "cache.h"
#include "builtin.h" #include "builtin.h"
@ -32,6 +33,113 @@ static void prepend_to_path(const char *dir, int len)
setenv("PATH", path, 1); 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; const char git_version_string[] = GIT_VERSION;
static void handle_internal_command(int argc, const char **argv, char **envp) static void handle_internal_command(int argc, const char **argv, char **envp)
@ -94,6 +202,7 @@ int main(int argc, const char **argv, char **envp)
char *slash = strrchr(cmd, '/'); char *slash = strrchr(cmd, '/');
char git_command[PATH_MAX + 1]; char git_command[PATH_MAX + 1];
const char *exec_path = NULL; const char *exec_path = NULL;
int done_alias = 0;
/* /*
* Take the basename of argv[0] as the command * Take the basename of argv[0] as the command
@ -178,11 +287,21 @@ int main(int argc, const char **argv, char **envp)
exec_path = git_exec_path(); exec_path = git_exec_path();
prepend_to_path(exec_path, strlen(exec_path)); prepend_to_path(exec_path, strlen(exec_path));
/* See if it's an internal command */ while (1) {
handle_internal_command(argc, argv, envp); /* See if it's an internal command */
handle_internal_command(argc, argv, envp);
/* .. then try the external ones */ /* .. then try the external ones */
execv_git_cmd(argv); 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) if (errno == ENOENT)
cmd_usage(0, exec_path, "'%s' is not a git-command", cmd); cmd_usage(0, exec_path, "'%s' is not a git-command", cmd);

View File

@ -463,48 +463,21 @@ static void rehash_objects(void)
} }
} }
struct name_path { static unsigned name_hash(const char *name)
struct name_path *up;
const char *elem;
int len;
};
#define DIRBITS 12
static unsigned name_hash(struct name_path *path, const char *name)
{ {
struct name_path *p = path; unsigned char c;
const char *n = name + strlen(name); unsigned hash = 0;
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;
}
}
/* /*
* Make sure "Makefile" and "t/Makefile" are hashed separately * This effectively just creates a sortable number from the
* but close enough. * last sixteen non-whitespace characters. Last characters
* count "most", so things that end in ".c" sort together.
*/ */
hash = (name_hash<<DIRBITS) | (hash & ((1U<<DIRBITS )-1)); while ((c = *name++) != 0) {
if (isspace(c))
continue;
hash = (hash >> 2) + (c << 24);
}
return hash; return hash;
} }
@ -686,9 +659,9 @@ static int name_cmp_len(const char *name)
} }
static void add_pbase_object(struct tree_desc *tree, static void add_pbase_object(struct tree_desc *tree,
struct name_path *up,
const char *name, const char *name,
int cmplen) int cmplen,
const char *fullname)
{ {
struct name_entry entry; struct name_entry entry;
@ -702,13 +675,12 @@ static void add_pbase_object(struct tree_desc *tree,
sha1_object_info(entry.sha1, type, &size)) sha1_object_info(entry.sha1, type, &size))
continue; continue;
if (name[cmplen] != '/') { if (name[cmplen] != '/') {
unsigned hash = name_hash(up, name); unsigned hash = name_hash(fullname);
add_object_entry(entry.sha1, hash, 1); add_object_entry(entry.sha1, hash, 1);
return; return;
} }
if (!strcmp(type, tree_type)) { if (!strcmp(type, tree_type)) {
struct tree_desc sub; struct tree_desc sub;
struct name_path me;
struct pbase_tree_cache *tree; struct pbase_tree_cache *tree;
const char *down = name+cmplen+1; const char *down = name+cmplen+1;
int downlen = name_cmp_len(down); 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.buf = tree->tree_data;
sub.size = tree->tree_size; sub.size = tree->tree_size;
me.up = up; add_pbase_object(&sub, down, downlen, fullname);
me.elem = entry.path;
me.len = entry.pathlen;
add_pbase_object(&sub, &me, down, downlen);
pbase_tree_put(tree); 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) { for (it = pbase_tree; it; it = it->next) {
if (cmplen == 0) { if (cmplen == 0) {
hash = name_hash(NULL, ""); hash = name_hash("");
add_object_entry(it->pcache.sha1, hash, 1); add_object_entry(it->pcache.sha1, hash, 1);
} }
else { else {
struct tree_desc tree; struct tree_desc tree;
tree.buf = it->pcache.tree_data; tree.buf = it->pcache.tree_data;
tree.size = it->pcache.tree_size; 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)) if (get_sha1_hex(line, sha1))
die("expected sha1, got garbage:\n %s", line); 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_preferred_base_object(line+41, hash);
add_object_entry(sha1, hash, 0); add_object_entry(sha1, hash, 0);
} }