* Re: Mozilla .git tree
From: Shawn Pearce @ 2006-09-02 2:04 UTC (permalink / raw)
To: Junio C Hamano; +Cc: Nicolas Pitre, git, Linus Torvalds
In-Reply-To: <7vr6yw58xp.fsf@assigned-by-dhcp.cox.net>
Junio C Hamano <junkio@cox.net> wrote:
[snip]
> +A new style .idx file begins with a signature, "\377tOc", and a
> +version number as a 4-byte network byte order integer. The version
> +of this implementation is 2.
Ick. I understand why you did this (and thanks for such a good
explanation of it by the way) but what a horrible signature number
and way to wedge in a version number.
>From now on I propose that if we write a file - especially a binary
file - to disk that we always include a 4 byte version number into
the header of the file. Then we can avoid trying to wedge this into
the file after the fact when some worthwhile improvement requires
changing the format.
I think we probably should have done this when the binary headers
were introduced into loose objects. Would 4 bytes of file format
version number with an (initial version number which wasn't 0x78
in byte 0 and failed the % 31 test) really have hurt that much in
a loose object?
[snip]
> + . 4-byte network byte order integer, recording the location of the
> + next object in the main toc table.
Why not just the 4 byte object entry length? To load an object we
have to go find the next object in the idx file so we can compute
the offset difference. On very large packs (e.g. the Mozilla pack)
the index is 46 MiB. The jump across the index could be the entire
thing from back to front just to compute the size of an object when
the fan-out table and the binary search process really only poked
the tail end of the index when searching for the entry. So we're
demand paging in the front of the index just to compute a length
Sure the scheme you outlined allows a 64 bit difference but
uncompressed objects already can't be larger than 2**32-1 and we
could just as easily move that limit down to say 2**32-16 to leave
room for the object header and zlib header.
--
Shawn.
--
VGER BF report: U 0.5
^ permalink raw reply
* Re: [PATCH] pack-objects: re-validate data we copy from elsewhere.
From: Junio C Hamano @ 2006-09-02 3:52 UTC (permalink / raw)
To: Linus Torvalds; +Cc: git
In-Reply-To: <Pine.LNX.4.64.0609011721390.27779@g5.osdl.org>
Linus Torvalds <torvalds@osdl.org> writes:
> On Fri, 1 Sep 2006, Junio C Hamano wrote:
>>
>> [...] Instead make sure they are not corrupt, but
>> do so only when we are not streaming to stdout, [...]
>
> Hmm. I see you making pack_to_stdout available to those functions, but I
> don't actually see you using it - looks like you revalidate regardless.
>
> Which is safe, of course, but it doesn't match your description ;)
But "git repack -a -d", which you now consider almost being
free, in the recent kernel repository counts 300k objects, and
reuses 298k objects or so. That means we expand and recompress
that many objects, totalling 120MB.
It might be worthwhile to disable revalidate reused objects
individually and instead scan and checksum the entire .pack file
when the number of objects being reused exceeds certain
threshold, relative to the number of objects in existing pack,
perhaps.
--
VGER BF report: U 0.5
^ permalink raw reply
* Re: Mozilla .git tree
From: Junio C Hamano @ 2006-09-02 4:01 UTC (permalink / raw)
To: Shawn Pearce; +Cc: git
In-Reply-To: <20060902011950.GB24234@spearce.org>
Shawn Pearce <spearce@spearce.org> writes:
> What I did in fast-import was give inflate whatever was left in
> the current mapping; then if I got a Z_OK or Z_BUF_ERROR back from
> inflate I move the mapping to the next 128 MiB chunk and reset my
> z_stream's next_in/avail_in accordingly, then recall inflate.
Makes sense.
> But having the length or ending offset in the index will help with
> copying the object during a repack as well as prevent us from needing
> to guess during accesses.
Actually pack-objects already builds the reverse index without
the help from the updated .idx file format, so while having it
pre-built in .idx may help, it is not necessary for it. With
your "feed until the end of the current window and if we need
more map in the next window" logic, we do not even need to know
the length of each entry at runtime either.
So I am inclined to chuck the previous patch that records the
next object number in each entry. We could keep the 64-bit
offset, which would make an entry to be 28-byte instead of
32-byte.
--
VGER BF report: U 0.5
^ permalink raw reply
* Re: VGER BF report?
From: Sam Ravnborg @ 2006-09-02 5:58 UTC (permalink / raw)
To: Johannes Schindelin; +Cc: git
In-Reply-To: <Pine.LNX.4.63.0609020338430.28360@wbgn013.biozentrum.uni-wuerzburg.de>
On Sat, Sep 02, 2006 at 03:39:30AM +0200, Johannes Schindelin wrote:
> > VGER BF report: H 0.0110285
>
> What is this?
vger.kernel.org is experimentibg with bogofilter.
Seems to be a ham score.
Matti announced the use of bogofilter on linux-kernel yesterday.
Sam
--
VGER BF report: U 0.497275
^ permalink raw reply
* Re: [PATCH 0/3] git-daemon: plug new upload-tar command
From: Franck Bui-Huu @ 2006-09-02 8:14 UTC (permalink / raw)
To: Rene Scharfe; +Cc: junkio, git
In-Reply-To: <44F72039.3040206@lsrfire.ath.cx>
Hi,
2006/8/31, Rene Scharfe <rene.scharfe@lsrfire.ath.cx>:
> Junio has similar code in the 'next' branch. And he correctly pointed
duh, wasn't aware of it. :(
> out that with the arrival of git-zip-tree the time has come to think
> about a format independent tree-to-archive converter command to avoid
> re-implementing essentially the same thing under the names of
> git-upload-zip, git-upload-rar etc.
>
That would make sense if you're going to implement any possible
archive formats ;)
> I'm trying for a few days now to find time for implementing a
> git-archive command, but I'm failing. And I won't be able to do so
> before the weekend (at least).
>
> I propose to make the command line syntax more similar to the one of
> git-ls-tree (e.g. --prefix instead of optional second non-option
> parameter for base dir, support for path specs). In a previous mail I
> also proposed to merge the upload command into git-archive, but now that
> I thought a bit about it it doesn't make sense to me anymore.
>
Maybe it's time for a "upload-archive" that would implement a common
git archiver protocol used by all git-{zip,tar,..}-tree. And by that
time move git-tar-tree protocol stuff into git-archive.
> So if you beat me to it, that would be great. Or if you have a better
> idea, that would be also great. :-)
>
Well I'll try to start something, not sure to have a lot of time
though. Please contact me before starting anything, I would be sad to
write something for /dev/null again ;)
One point would make git-tar-tree able to compress data and git-daemon
would refuse any requests for a non compressed archive format.
--
Franck
--
VGER BF report: U 0.499999
^ permalink raw reply
* [PATCH] Replace uses of strdup with xstrdup.
From: Shawn Pearce @ 2006-09-02 4:16 UTC (permalink / raw)
To: Junio C Hamano; +Cc: git
Like xmalloc and xrealloc xstrdup dies with a useful message if
the native strdup() implementation returns NULL rather than a
valid pointer.
I just tried to use xstrdup in new code and found it to be missing.
However I expected it to be present as xmalloc and xrealloc are
already commonly used throughout the code.
Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
---
blame.c | 2 +-
builtin-apply.c | 2 +-
builtin-fmt-merge-msg.c | 22 +++++++++++-----------
builtin-grep.c | 2 +-
builtin-name-rev.c | 2 +-
builtin-prune.c | 2 +-
builtin-push.c | 10 +++++-----
builtin-repo-config.c | 6 +++---
builtin-rev-list.c | 4 ++--
builtin-rm.c | 2 +-
builtin-show-branch.c | 6 +++---
builtin-symbolic-ref.c | 4 ++--
builtin-tar-tree.c | 2 +-
builtin-upload-tar.c | 2 +-
builtin-zip-tree.c | 4 ++--
commit.c | 2 +-
config.c | 8 ++++----
connect.c | 6 +++---
diff.c | 4 ++--
environment.c | 2 +-
fetch.c | 4 ++--
fsck-objects.c | 2 +-
git-compat-util.h | 8 ++++++++
git.c | 2 +-
http-fetch.c | 2 +-
http-push.c | 6 +++---
imap-send.c | 12 ++++++------
merge-file.c | 2 +-
merge-recursive.c | 14 +++++++-------
merge-tree.c | 4 ++--
path-list.c | 2 +-
refs.c | 4 ++--
server-info.c | 2 +-
sha1_file.c | 8 ++++----
sha1_name.c | 4 ++--
35 files changed, 89 insertions(+), 81 deletions(-)
diff --git a/blame.c b/blame.c
index 8968046..8cfd5d9 100644
--- a/blame.c
+++ b/blame.c
@@ -617,7 +617,7 @@ static void simplify_commit(struct rev_i
if (new_name) {
struct util_info* putil = get_util(p);
if (!putil->pathname)
- putil->pathname = strdup(new_name);
+ putil->pathname = xstrdup(new_name);
} else {
*pp = parent->next;
continue;
diff --git a/builtin-apply.c b/builtin-apply.c
index 1a1deaf..872c800 100644
--- a/builtin-apply.c
+++ b/builtin-apply.c
@@ -2449,7 +2449,7 @@ static int apply_patch(int fd, const cha
static int git_apply_config(const char *var, const char *value)
{
if (!strcmp(var, "apply.whitespace")) {
- apply_default_whitespace = strdup(value);
+ apply_default_whitespace = xstrdup(value);
return 0;
}
return git_default_config(var, value);
diff --git a/builtin-fmt-merge-msg.c b/builtin-fmt-merge-msg.c
index ed59e77..b946b7d 100644
--- a/builtin-fmt-merge-msg.c
+++ b/builtin-fmt-merge-msg.c
@@ -111,29 +111,29 @@ static int handle_line(char *line)
i = find_in_list(&srcs, src);
if (i < 0) {
i = srcs.nr;
- append_to_list(&srcs, strdup(src),
+ append_to_list(&srcs, xstrdup(src),
xcalloc(1, sizeof(struct src_data)));
}
src_data = srcs.payload[i];
if (pulling_head) {
- origin = strdup(src);
+ origin = xstrdup(src);
src_data->head_status |= 1;
} else if (!strncmp(line, "branch ", 7)) {
- origin = strdup(line + 7);
+ origin = xstrdup(line + 7);
append_to_list(&src_data->branch, origin, NULL);
src_data->head_status |= 2;
} else if (!strncmp(line, "tag ", 4)) {
origin = line;
- append_to_list(&src_data->tag, strdup(origin + 4), NULL);
+ append_to_list(&src_data->tag, xstrdup(origin + 4), NULL);
src_data->head_status |= 2;
} else if (!strncmp(line, "remote branch ", 14)) {
- origin = strdup(line + 14);
+ origin = xstrdup(line + 14);
append_to_list(&src_data->r_branch, origin, NULL);
src_data->head_status |= 2;
} else {
- origin = strdup(src);
- append_to_list(&src_data->generic, strdup(line), NULL);
+ origin = xstrdup(src);
+ append_to_list(&src_data->generic, xstrdup(line), NULL);
src_data->head_status |= 2;
}
@@ -145,7 +145,7 @@ static int handle_line(char *line)
new_origin[len - 1] = 0;
origin = new_origin;
} else
- origin = strdup(origin);
+ origin = xstrdup(origin);
} else {
char *new_origin = xmalloc(strlen(origin) + strlen(src) + 5);
sprintf(new_origin, "%s of %s", origin, src);
@@ -203,7 +203,7 @@ static void shortlog(const char *name, u
bol = strstr(commit->buffer, "\n\n");
if (!bol) {
- append_to_list(&subjects, strdup(sha1_to_hex(
+ append_to_list(&subjects, xstrdup(sha1_to_hex(
commit->object.sha1)),
NULL);
continue;
@@ -218,7 +218,7 @@ static void shortlog(const char *name, u
memcpy(oneline, bol, len);
oneline[len] = 0;
} else
- oneline = strdup(bol);
+ oneline = xstrdup(bol);
append_to_list(&subjects, oneline, NULL);
}
@@ -277,7 +277,7 @@ int cmd_fmt_merge_msg(int argc, const ch
usage(fmt_merge_msg_usage);
/* get current branch */
- head = strdup(git_path("HEAD"));
+ head = xstrdup(git_path("HEAD"));
current_branch = resolve_ref(head, head_sha1, 1);
current_branch += strlen(head) - 4;
free((char *)head);
diff --git a/builtin-grep.c b/builtin-grep.c
index 8213ce2..6430f6d 100644
--- a/builtin-grep.c
+++ b/builtin-grep.c
@@ -1048,7 +1048,7 @@ int cmd_grep(int argc, const char **argv
/* ignore empty line like grep does */
if (!buf[0])
continue;
- add_pattern(&opt, strdup(buf), argv[1], ++lno,
+ add_pattern(&opt, xstrdup(buf), argv[1], ++lno,
GREP_PATTERN);
}
fclose(patterns);
diff --git a/builtin-name-rev.c b/builtin-name-rev.c
index d44e782..52886b6 100644
--- a/builtin-name-rev.c
+++ b/builtin-name-rev.c
@@ -100,7 +100,7 @@ static int name_ref(const char *path, co
else if (!strncmp(path, "refs/", 5))
path = path + 5;
- name_rev(commit, strdup(path), 0, 0, deref);
+ name_rev(commit, xstrdup(path), 0, 0, deref);
}
return 0;
}
diff --git a/builtin-prune.c b/builtin-prune.c
index fc885ce..6228c79 100644
--- a/builtin-prune.c
+++ b/builtin-prune.c
@@ -106,7 +106,7 @@ static void process_tree(struct tree *tr
obj->flags |= SEEN;
if (parse_tree(tree) < 0)
die("bad tree object %s", sha1_to_hex(obj->sha1));
- name = strdup(name);
+ name = xstrdup(name);
add_object(obj, p, path, name);
me.up = path;
me.elem = name;
diff --git a/builtin-push.c b/builtin-push.c
index ada8338..c43f256 100644
--- a/builtin-push.c
+++ b/builtin-push.c
@@ -33,7 +33,7 @@ static int expand_one_ref(const char *re
ref += 5;
if (!strncmp(ref, "tags/", 5))
- add_refspec(strdup(ref));
+ add_refspec(xstrdup(ref));
return 0;
}
@@ -100,12 +100,12 @@ static int get_remotes_uri(const char *r
if (!is_refspec) {
if (n < MAX_URI)
- uri[n++] = strdup(s);
+ uri[n++] = xstrdup(s);
else
error("more than %d URL's specified, ignoring the rest", MAX_URI);
}
else if (is_refspec && !has_explicit_refspec)
- add_refspec(strdup(s));
+ add_refspec(xstrdup(s));
}
fclose(f);
if (!n)
@@ -125,13 +125,13 @@ static int get_remote_config(const char*
!strncmp(key + 7, config_repo, config_repo_len)) {
if (!strcmp(key + 7 + config_repo_len, ".url")) {
if (config_current_uri < MAX_URI)
- config_uri[config_current_uri++] = strdup(value);
+ config_uri[config_current_uri++] = xstrdup(value);
else
error("more than %d URL's specified, ignoring the rest", MAX_URI);
}
else if (config_get_refspecs &&
!strcmp(key + 7 + config_repo_len, ".push"))
- add_refspec(strdup(value));
+ add_refspec(xstrdup(value));
}
return 0;
}
diff --git a/builtin-repo-config.c b/builtin-repo-config.c
index d19f7dc..f60cee1 100644
--- a/builtin-repo-config.c
+++ b/builtin-repo-config.c
@@ -72,12 +72,12 @@ static int get_value(const char* key_, c
const char *home = getenv("HOME");
local = getenv("GIT_CONFIG_LOCAL");
if (!local)
- local = repo_config = strdup(git_path("config"));
+ local = repo_config = xstrdup(git_path("config"));
if (home)
- global = strdup(mkpath("%s/.gitconfig", home));
+ global = xstrdup(mkpath("%s/.gitconfig", home));
}
- key = strdup(key_);
+ key = xstrdup(key_);
for (tl=key+strlen(key)-1; tl >= key && *tl != '.'; --tl)
*tl = tolower(*tl);
for (tl=key; *tl && *tl != '.'; ++tl)
diff --git a/builtin-rev-list.c b/builtin-rev-list.c
index 402af8e..8437454 100644
--- a/builtin-rev-list.c
+++ b/builtin-rev-list.c
@@ -109,7 +109,7 @@ static void process_blob(struct blob *bl
if (obj->flags & (UNINTERESTING | SEEN))
return;
obj->flags |= SEEN;
- name = strdup(name);
+ name = xstrdup(name);
add_object(obj, p, path, name);
}
@@ -130,7 +130,7 @@ static void process_tree(struct tree *tr
if (parse_tree(tree) < 0)
die("bad tree object %s", sha1_to_hex(obj->sha1));
obj->flags |= SEEN;
- name = strdup(name);
+ name = xstrdup(name);
add_object(obj, p, path, name);
me.up = path;
me.elem = name;
diff --git a/builtin-rm.c b/builtin-rm.c
index 593d867..33d04bd 100644
--- a/builtin-rm.c
+++ b/builtin-rm.c
@@ -32,7 +32,7 @@ static int remove_file(const char *name)
ret = unlink(name);
if (!ret && (slash = strrchr(name, '/'))) {
- char *n = strdup(name);
+ char *n = xstrdup(name);
do {
n[slash - name] = 0;
name = n;
diff --git a/builtin-show-branch.c b/builtin-show-branch.c
index d7de18e..578c9fa 100644
--- a/builtin-show-branch.c
+++ b/builtin-show-branch.c
@@ -163,7 +163,7 @@ static void name_commits(struct commit_l
en += sprintf(en, "^");
else
en += sprintf(en, "^%d", nth);
- name_commit(p, strdup(newname), 0);
+ name_commit(p, xstrdup(newname), 0);
i++;
name_first_parent_chain(p);
}
@@ -364,7 +364,7 @@ static int append_ref(const char *refnam
refname, MAX_REVS);
return 0;
}
- ref_name[ref_name_cnt++] = strdup(refname);
+ ref_name[ref_name_cnt++] = xstrdup(refname);
ref_name[ref_name_cnt] = NULL;
return 0;
}
@@ -521,7 +521,7 @@ static int git_show_branch_config(const
default_alloc = default_alloc * 3 / 2 + 20;
default_arg = xrealloc(default_arg, sizeof *default_arg * default_alloc);
}
- default_arg[default_num++] = strdup(value);
+ default_arg[default_num++] = xstrdup(value);
default_arg[default_num] = NULL;
return 0;
}
diff --git a/builtin-symbolic-ref.c b/builtin-symbolic-ref.c
index b4ec6f2..1d3a5e2 100644
--- a/builtin-symbolic-ref.c
+++ b/builtin-symbolic-ref.c
@@ -7,7 +7,7 @@ static const char git_symbolic_ref_usage
static void check_symref(const char *HEAD)
{
unsigned char sha1[20];
- const char *git_HEAD = strdup(git_path("%s", HEAD));
+ const char *git_HEAD = xstrdup(git_path("%s", HEAD));
const char *git_refs_heads_master = resolve_ref(git_HEAD, sha1, 0);
if (git_refs_heads_master) {
/* we want to strip the .git/ part */
@@ -26,7 +26,7 @@ int cmd_symbolic_ref(int argc, const cha
check_symref(argv[1]);
break;
case 3:
- create_symref(strdup(git_path("%s", argv[1])), argv[2]);
+ create_symref(xstrdup(git_path("%s", argv[1])), argv[2]);
break;
default:
usage(git_symbolic_ref_usage);
diff --git a/builtin-tar-tree.c b/builtin-tar-tree.c
index 61a4135..fa666f7 100644
--- a/builtin-tar-tree.c
+++ b/builtin-tar-tree.c
@@ -351,7 +351,7 @@ static int remote_tar(int argc, const ch
usage(tar_tree_usage);
/* --remote=<repo> */
- url = strdup(argv[1]+9);
+ url = xstrdup(argv[1]+9);
pid = git_connect(fd, url, exec);
if (pid < 0)
return 1;
diff --git a/builtin-upload-tar.c b/builtin-upload-tar.c
index 7b401bb..06a945a 100644
--- a/builtin-upload-tar.c
+++ b/builtin-upload-tar.c
@@ -53,7 +53,7 @@ int cmd_upload_tar(int argc, const char
return nak("expected (optional) base");
if (buf[len-1] == '\n')
buf[--len] = 0;
- base = strdup(buf + 5);
+ base = xstrdup(buf + 5);
len = packet_read_line(0, buf, sizeof(buf));
}
if (len)
diff --git a/builtin-zip-tree.c b/builtin-zip-tree.c
index a5b834d..1c1f683 100644
--- a/builtin-zip-tree.c
+++ b/builtin-zip-tree.c
@@ -311,11 +311,11 @@ int cmd_zip_tree(int argc, const char **
switch (argc) {
case 3:
- base = strdup(argv[2]);
+ base = xstrdup(argv[2]);
baselen = strlen(base);
break;
case 2:
- base = strdup("");
+ base = xstrdup("");
baselen = 0;
break;
default:
diff --git a/commit.c b/commit.c
index 3f4bc31..e5aa22e 100644
--- a/commit.c
+++ b/commit.c
@@ -233,7 +233,7 @@ static void prepare_commit_graft(void)
}
if (last_graft_file)
free(last_graft_file);
- last_graft_file = strdup(graft_file);
+ last_graft_file = xstrdup(graft_file);
read_graft_file(graft_file);
commit_graft_prepared = 1;
diff --git a/config.c b/config.c
index c0897cc..e8f0caf 100644
--- a/config.c
+++ b/config.c
@@ -350,11 +350,11 @@ int git_config(config_fn_t fn)
home = getenv("HOME");
filename = getenv("GIT_CONFIG_LOCAL");
if (!filename)
- filename = repo_config = strdup(git_path("config"));
+ filename = repo_config = xstrdup(git_path("config"));
}
if (home) {
- char *user_config = strdup(mkpath("%s/.gitconfig", home));
+ char *user_config = xstrdup(mkpath("%s/.gitconfig", home));
if (!access(user_config, R_OK))
ret = git_config_from_file(fn, user_config);
free(user_config);
@@ -545,8 +545,8 @@ int git_config_set_multivar(const char*
if (!config_filename)
config_filename = git_path("config");
}
- config_filename = strdup(config_filename);
- lock_file = strdup(mkpath("%s.lock", config_filename));
+ config_filename = xstrdup(config_filename);
+ lock_file = xstrdup(mkpath("%s.lock", config_filename));
/*
* Since "key" actually contains the section name and the real
diff --git a/connect.c b/connect.c
index e501ccc..06ef387 100644
--- a/connect.c
+++ b/connect.c
@@ -69,7 +69,7 @@ struct ref **get_remote_heads(int in, st
if (len != name_len + 41) {
if (server_capabilities)
free(server_capabilities);
- server_capabilities = strdup(name + name_len + 1);
+ server_capabilities = xstrdup(name + name_len + 1);
}
if (!check_ref(name, name_len, flags))
@@ -661,7 +661,7 @@ int git_connect(int fd[2], char *url, co
if (path[1] == '~')
path++;
else {
- path = strdup(ptr);
+ path = xstrdup(ptr);
free_path = 1;
}
@@ -672,7 +672,7 @@ int git_connect(int fd[2], char *url, co
/* These underlying connection commands die() if they
* cannot connect.
*/
- char *target_host = strdup(host);
+ char *target_host = xstrdup(host);
if (git_use_proxy(host))
git_proxy_connect(fd, host);
else
diff --git a/diff.c b/diff.c
index 70699fd..9dcbda3 100644
--- a/diff.c
+++ b/diff.c
@@ -216,7 +216,7 @@ static char *quote_one(const char *str)
return NULL;
needlen = quote_c_style(str, NULL, NULL, 0);
if (!needlen)
- return strdup(str);
+ return xstrdup(str);
xp = xmalloc(needlen + 1);
quote_c_style(str, xp, NULL, 0);
return xp;
@@ -658,7 +658,7 @@ static struct diffstat_file *diffstat_ad
x->is_renamed = 1;
}
else
- x->name = strdup(name_a);
+ x->name = xstrdup(name_a);
return x;
}
diff --git a/environment.c b/environment.c
index cd276b0..0ab3385 100644
--- a/environment.c
+++ b/environment.c
@@ -67,7 +67,7 @@ void setup_git(char *new_git_dir, char *
free(git_graft_file);
git_graft_file = new_git_graft_file;
if (!git_graft_file) {
- git_graft_file = strdup(git_path("info/grafts"));
+ git_graft_file = xstrdup(git_path("info/grafts"));
dyn_git_graft_file = 1;
} else {
dyn_git_graft_file = 0;
diff --git a/fetch.c b/fetch.c
index 7d3812c..34df8d3 100644
--- a/fetch.c
+++ b/fetch.c
@@ -234,8 +234,8 @@ int pull_targets_stdin(char ***target, c
*target = xrealloc(*target, targets_alloc * sizeof(**target));
*write_ref = xrealloc(*write_ref, targets_alloc * sizeof(**write_ref));
}
- (*target)[targets] = strdup(tg_one);
- (*write_ref)[targets] = rf_one ? strdup(rf_one) : NULL;
+ (*target)[targets] = xstrdup(tg_one);
+ (*write_ref)[targets] = rf_one ? xstrdup(rf_one) : NULL;
targets++;
}
return targets;
diff --git a/fsck-objects.c b/fsck-objects.c
index 24286de..4d994f3 100644
--- a/fsck-objects.c
+++ b/fsck-objects.c
@@ -458,7 +458,7 @@ static void fsck_object_dir(const char *
static int fsck_head_link(void)
{
unsigned char sha1[20];
- const char *git_HEAD = strdup(git_path("HEAD"));
+ const char *git_HEAD = xstrdup(git_path("HEAD"));
const char *git_refs_heads_master = resolve_ref(git_HEAD, sha1, 1);
int pfxlen = strlen(git_HEAD) - 4; /* strip .../.git/ part */
diff --git a/git-compat-util.h b/git-compat-util.h
index 91f2b0d..552b8ec 100644
--- a/git-compat-util.h
+++ b/git-compat-util.h
@@ -84,6 +84,14 @@ #define strlcpy gitstrlcpy
extern size_t gitstrlcpy(char *, const char *, size_t);
#endif
+static inline char* xstrdup(const char *str)
+{
+ char *ret = strdup(str);
+ if (!ret)
+ die("Out of memory, strdup failed");
+ return ret;
+}
+
static inline void *xmalloc(size_t size)
{
void *ret = malloc(size);
diff --git a/git.c b/git.c
index 403fb3a..1d00111 100644
--- a/git.c
+++ b/git.c
@@ -97,7 +97,7 @@ static char *alias_string;
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);
+ alias_string = xstrdup(value);
}
return 0;
}
diff --git a/http-fetch.c b/http-fetch.c
index 6806f36..fac1760 100644
--- a/http-fetch.c
+++ b/http-fetch.c
@@ -787,7 +787,7 @@ static int remote_ls(struct alt_base *re
ls.flags = flags;
ls.repo = repo;
- ls.path = strdup(path);
+ ls.path = xstrdup(path);
ls.dentry_name = NULL;
ls.dentry_flags = 0;
ls.userData = userData;
diff --git a/http-push.c b/http-push.c
index 7814666..670ff00 100644
--- a/http-push.c
+++ b/http-push.c
@@ -1539,7 +1539,7 @@ static void remote_ls(const char *path,
struct remote_ls_ctx ls;
ls.flags = flags;
- ls.path = strdup(path);
+ ls.path = xstrdup(path);
ls.dentry_name = NULL;
ls.dentry_flags = 0;
ls.userData = userData;
@@ -1738,7 +1738,7 @@ static struct object_list **process_tree
die("bad tree object %s", sha1_to_hex(obj->sha1));
obj->flags |= SEEN;
- name = strdup(name);
+ name = xstrdup(name);
p = add_one_object(obj, p);
me.up = path;
me.elem = name;
@@ -2467,7 +2467,7 @@ int main(int argc, char **argv)
/* Set up revision info for this refspec */
commit_argc = 3;
- new_sha1_hex = strdup(sha1_to_hex(ref->new_sha1));
+ new_sha1_hex = xstrdup(sha1_to_hex(ref->new_sha1));
old_sha1_hex = NULL;
commit_argv[1] = "--objects";
commit_argv[2] = new_sha1_hex;
diff --git a/imap-send.c b/imap-send.c
index 6a52dbd..362e474 100644
--- a/imap-send.c
+++ b/imap-send.c
@@ -1007,7 +1007,7 @@ imap_open_store( imap_server_conf_t *srv
* getpass() returns a pointer to a static buffer. make a copy
* for long term storage.
*/
- srvc->pass = strdup( arg );
+ srvc->pass = xstrdup( arg );
}
if (CAP(NOLOGIN)) {
fprintf( stderr, "Skipping account %s@%s, server forbids LOGIN\n", srvc->user, srvc->host );
@@ -1263,7 +1263,7 @@ git_imap_config(const char *key, const c
key += sizeof imap_key - 1;
if (!strcmp( "folder", key )) {
- imap_folder = strdup( val );
+ imap_folder = xstrdup( val );
} else if (!strcmp( "host", key )) {
{
if (!strncmp( "imap:", val, 5 ))
@@ -1273,16 +1273,16 @@ git_imap_config(const char *key, const c
}
if (!strncmp( "//", val, 2 ))
val += 2;
- server.host = strdup( val );
+ server.host = xstrdup( val );
}
else if (!strcmp( "user", key ))
- server.user = strdup( val );
+ server.user = xstrdup( val );
else if (!strcmp( "pass", key ))
- server.pass = strdup( val );
+ server.pass = xstrdup( val );
else if (!strcmp( "port", key ))
server.port = git_config_int( key, val );
else if (!strcmp( "tunnel", key ))
- server.tunnel = strdup( val );
+ server.tunnel = xstrdup( val );
return 0;
}
diff --git a/merge-file.c b/merge-file.c
index f32c653..fc9b148 100644
--- a/merge-file.c
+++ b/merge-file.c
@@ -21,7 +21,7 @@ static const char *write_temp_file(mmfil
fd = mkstemp(filename);
if (fd < 0)
return NULL;
- filename = strdup(filename);
+ filename = xstrdup(filename);
if (f->size != xwrite(fd, f->ptr, f->size)) {
rm_temp_file(filename);
return NULL;
diff --git a/merge-recursive.c b/merge-recursive.c
index 48b2763..611cd95 100644
--- a/merge-recursive.c
+++ b/merge-recursive.c
@@ -513,8 +513,8 @@ static char *unique_path(const char *pat
static int mkdir_p(const char *path, unsigned long mode)
{
- /* path points to cache entries, so strdup before messing with it */
- char *buf = strdup(path);
+ /* path points to cache entries, so xstrdup before messing with it */
+ char *buf = xstrdup(path);
int result = safe_create_leading_directories(buf);
free(buf);
return result;
@@ -668,9 +668,9 @@ static struct merge_file_info merge_file
git_unpack_file(a->sha1, src1);
git_unpack_file(b->sha1, src2);
- argv[2] = la = strdup(mkpath("%s/%s", branch1, a->path));
- argv[6] = lb = strdup(mkpath("%s/%s", branch2, b->path));
- argv[4] = lo = strdup(mkpath("orig/%s", o->path));
+ argv[2] = la = xstrdup(mkpath("%s/%s", branch1, a->path));
+ argv[6] = lb = xstrdup(mkpath("%s/%s", branch2, b->path));
+ argv[4] = lo = xstrdup(mkpath("orig/%s", o->path));
argv[7] = src1;
argv[8] = orig;
argv[9] = src2,
@@ -1314,9 +1314,9 @@ int main(int argc, char *argv[])
original_index_file = getenv("GIT_INDEX_FILE");
if (!original_index_file)
- original_index_file = strdup(git_path("index"));
+ original_index_file = xstrdup(git_path("index"));
- temporary_index_file = strdup(git_path("mrg-rcrsv-tmp-idx"));
+ temporary_index_file = xstrdup(git_path("mrg-rcrsv-tmp-idx"));
if (argc < 4)
die("Usage: %s <base>... -- <head> <remote> ...\n", argv[0]);
diff --git a/merge-tree.c b/merge-tree.c
index c2e9a86..60df758 100644
--- a/merge-tree.c
+++ b/merge-tree.c
@@ -177,7 +177,7 @@ static void resolve(const char *base, st
if (!branch1)
return;
- path = strdup(mkpath("%s%s", base, result->path));
+ path = xstrdup(mkpath("%s%s", base, result->path));
orig = create_entry(2, branch1->mode, branch1->sha1, path);
final = create_entry(0, result->mode, result->sha1, path);
@@ -233,7 +233,7 @@ static struct merge_list *link_entry(uns
if (entry)
path = entry->path;
else
- path = strdup(mkpath("%s%s", base, n->path));
+ path = xstrdup(mkpath("%s%s", base, n->path));
link = create_entry(stage, n->mode, n->sha1, path);
link->link = entry;
return link;
diff --git a/path-list.c b/path-list.c
index b1ee72d..0c332dc 100644
--- a/path-list.c
+++ b/path-list.c
@@ -45,7 +45,7 @@ static int add_entry(struct path_list *l
(list->nr - index)
* sizeof(struct path_list_item));
list->items[index].path = list->strdup_paths ?
- strdup(path) : (char *)path;
+ xstrdup(path) : (char *)path;
list->items[index].util = NULL;
list->nr++;
diff --git a/refs.c b/refs.c
index aab14fc..5e65314 100644
--- a/refs.c
+++ b/refs.c
@@ -313,8 +313,8 @@ static struct ref_lock *lock_ref_sha1_ba
}
lock->lk = xcalloc(1, sizeof(struct lock_file));
- lock->ref_file = strdup(path);
- lock->log_file = strdup(git_path("logs/%s", lock->ref_file + plen));
+ lock->ref_file = xstrdup(path);
+ lock->log_file = xstrdup(git_path("logs/%s", lock->ref_file + plen));
lock->force_write = lstat(lock->ref_file, &st) && errno == ENOENT;
if (safe_create_leading_directories(lock->ref_file))
diff --git a/server-info.c b/server-info.c
index 7df628f..2fb8f57 100644
--- a/server-info.c
+++ b/server-info.c
@@ -23,7 +23,7 @@ static int add_info_ref(const char *path
static int update_info_refs(int force)
{
- char *path0 = strdup(git_path("info/refs"));
+ char *path0 = xstrdup(git_path("info/refs"));
int len = strlen(path0);
char *path1 = xmalloc(len + 2);
diff --git a/sha1_file.c b/sha1_file.c
index fe9176a..feb55c6 100644
--- a/sha1_file.c
+++ b/sha1_file.c
@@ -115,7 +115,7 @@ static void fill_sha1_path(char *pathbuf
/*
* NOTE! This returns a statically allocated buffer, so you have to be
- * careful about using it. Do a "strdup()" if you need to save the
+ * careful about using it. Do a "xstrdup()" if you need to save the
* filename.
*
* Also note that this returns the location for creating. Reading
@@ -141,7 +141,7 @@ char *sha1_file_name(const unsigned char
name = base + len + 1;
if (last_objdir)
free((char *) last_objdir);
- last_objdir = strdup(sha1_file_directory);
+ last_objdir = xstrdup(sha1_file_directory);
}
fill_sha1_path(name, sha1);
return base;
@@ -164,7 +164,7 @@ char *sha1_pack_name(const unsigned char
name = base + len + 11;
if (last_objdir)
free((char *) last_objdir);
- last_objdir = strdup(sha1_file_directory);
+ last_objdir = xstrdup(sha1_file_directory);
}
buf = name;
@@ -195,7 +195,7 @@ char *sha1_pack_index_name(const unsigne
name = base + len + 11;
if (last_objdir)
free((char *) last_objdir);
- last_objdir = strdup(sha1_file_directory);
+ last_objdir = xstrdup(sha1_file_directory);
}
buf = name;
diff --git a/sha1_name.c b/sha1_name.c
index 60a2c0b..8fcc271 100644
--- a/sha1_name.c
+++ b/sha1_name.c
@@ -26,7 +26,7 @@ static int find_short_object_filename(in
fakeent->name[-1] = '/';
if (last_objdir)
free((char *) last_objdir);
- last_objdir = strdup(objdir);
+ last_objdir = xstrdup(objdir);
}
fakeent->next = alt_odb_list;
@@ -285,7 +285,7 @@ static int get_sha1_basic(const char *st
pathname = resolve_ref(git_path(*p, len, str), this_result, 1);
if (pathname) {
if (!refs_found++)
- real_path = strdup(pathname);
+ real_path = xstrdup(pathname);
if (!warn_ambiguous_refs)
break;
}
--
1.4.2.ga2654
--
VGER BF report: U 0.5
^ permalink raw reply related
* Re: [PATCH] pack-objects: re-validate data we copy from elsewhere.
From: Shawn Pearce @ 2006-09-02 4:52 UTC (permalink / raw)
To: Junio C Hamano; +Cc: Linus Torvalds, git
In-Reply-To: <7vd5ae3ox2.fsf@assigned-by-dhcp.cox.net>
Junio C Hamano <junkio@cox.net> wrote:
> It might be worthwhile to disable revalidate reused objects
> individually and instead scan and checksum the entire .pack file
> when the number of objects being reused exceeds certain
> threshold, relative to the number of objects in existing pack,
> perhaps.
Correct me if I'm wrong but didn't this revalidate check happen
because the SHA1 of the pack was correct but there was a bad bit
in the zlib stream?
If we are trying to detect such an error before removing the possibly
valid pack how are we supposed to do that if we are bypassing the
code on larger packs?
I think the better thing to do here is to not repack objects which
are already contained in very large packs. Just leave them be.
If the pack you are about to copy an object out of is over 25 MiB,
you aren't outputting to stdout and the object isn't needed
as a delta base in the new pack then don't copy it. Introduce a
new flag to git-pack-objects such as "--max-source-pack-size=100"
which can be used to change this 25 MiB threshold; setting it to
0 would act as "-a" does today.
This way users can repack with 'git repack -a -d' as though it were
free and much less frequently (such as once a year) combine their
medium sized packs together based on a larger maximum threshold
while still ignoring their really large historical packs.
Note that you are never bypassing the deflate validation; before
copying an object you *always* validate it is correct, even if the
source pack SHA1 is correct. But this time consuming validation
should not be a big issue as users shouldn't repack very large
packs very frequently with this strategy. E.g. some kernel devs
might repack once a year with --max-source-pack-size=512 (512 MiB)
but during normal use accept the 25 MiB default and the slightly
larger number of small packs that result.
--
Shawn.
--
VGER BF report: U 0.5
^ permalink raw reply
* Re: [PATCH] pack-objects: re-validate data we copy from elsewhere.
From: Junio C Hamano @ 2006-09-02 9:42 UTC (permalink / raw)
To: Shawn Pearce; +Cc: Linus Torvalds, git
In-Reply-To: <20060902045246.GB25146@spearce.org>
Shawn Pearce <spearce@spearce.org> writes:
> Junio C Hamano <junkio@cox.net> wrote:
>> It might be worthwhile to disable revalidate reused objects
>> individually and instead scan and checksum the entire .pack file
>> when the number of objects being reused exceeds certain
>> threshold, relative to the number of objects in existing pack,
>> perhaps.
>
> Correct me if I'm wrong but didn't this revalidate check happen
> because the SHA1 of the pack was correct but there was a bad bit
> in the zlib stream?
There are two more or less independent problems and you are
correct to point out that summing the entire .pack does not
catch one class of problem while it does catch the other.
The Linus's theory goes like this:
(1) A bit in an existing pack was damaged somehow. It might have
happened on the mothership machine when it was first created,
or after it was read and copied to the notebook via rsync.
(2) A 'repack -a -d' was done in a repository that had that
damanged pack, it decided to reuse a deflated object from the
existing, damaged pack, and copied that deflated
representation into a newly created pack without validating.
(3) The 'repack -a -d', when finishing the newly created pack,
computed a checksum over the whole new pack and wrote the
SHA-1 checksum in it.
Now, sha1_file() has check_packed_git_idx() that makes sure .idx
file is not corrupted; it runs the checksum over the whole .idx
data when it first maps in and makes sure the sum matches what
is recorded at the end. So if the corruption in (1) happened to
the .idx file, 'repack -a -d' in (2) would have noticed and
refused to use the corresponding .pack.
The problem is that there is however no corresponding "checksum
over the whole file before use" for .pack file during a normal
operation of use_packed_git(). Otherwise we would have caught
the corruption in the existing pack and prevented step (2) from
propagating the error.
The idea proposed by Linus and implemented in the patch in this
thread is to mitigate this by revalidating the individual pieces
we copy in (2). If we copy out most of what is in the existing
pack, however, it may be cheaper to do the "whole file checksum
before use" instead.
On the other hand, the "alpha particle at the right moment"
theory goes like this:
(1) write_object() gave the buffer to sha1write_compressed();
(2) sha1write_compressed() asked zlib to deflate the data and
received the result in buffer pointed by void *out;
(3) bit flipped in that buffer, after zlib finished writing
into it with the CRC;
(4) sha1write() wrote out the now-corrupt buffer, while
computing the correct checksum for the end result (which is
now corrupt).
This breakage will not be caught unless we revalidate everything
we copy out to the new pack.
--
VGER BF report: U 0.5
^ permalink raw reply
* Re: [PATCH] pack-objects: re-validate data we copy from elsewhere.
From: Junio C Hamano @ 2006-09-02 10:09 UTC (permalink / raw)
To: Shawn Pearce; +Cc: Linus Torvalds, git
In-Reply-To: <20060902045246.GB25146@spearce.org>
Shawn Pearce <spearce@spearce.org> writes:
> I think the better thing to do here is to not repack objects which
> are already contained in very large packs. Just leave them be.
I've been thinking about updating rev-list so that repack
can be used to organize packs into zero or more "archive packs"
and one "active pack".
repack without -a essentially boils down to:
rev-list --objects --all --unpacked |
pack-objects $new_pack
which picks up all live loose objects and create a new pack.
If rev-list had an extention that lets you say
rev-list --objects --all --unpacked=$active_pack |
pack-objects $new_pack
instead, to mean "all live loose objects but pretend as if
objects that are in this pack are also unpacked", then the
newly created pack would be perfect for updating $active_pack
by replacing it.
Perhaps something like this.
-- >8 --
diff --git a/builtin-count-objects.c b/builtin-count-objects.c
index 1d3729a..73c5982 100644
--- a/builtin-count-objects.c
+++ b/builtin-count-objects.c
@@ -62,7 +62,7 @@ static void count_objects(DIR *d, char *
hex[40] = 0;
if (get_sha1_hex(hex, sha1))
die("internal error");
- if (has_sha1_pack(sha1))
+ if (has_sha1_pack(sha1, NULL))
(*packed_loose)++;
}
}
diff --git a/builtin-prune-packed.c b/builtin-prune-packed.c
index d3dd94d..960db49 100644
--- a/builtin-prune-packed.c
+++ b/builtin-prune-packed.c
@@ -19,7 +19,7 @@ static void prune_dir(int i, DIR *dir, c
memcpy(hex+2, de->d_name, 38);
if (get_sha1_hex(hex, sha1))
continue;
- if (!has_sha1_pack(sha1))
+ if (!has_sha1_pack(sha1, NULL))
continue;
memcpy(pathname + len, de->d_name, 38);
if (dryrun)
diff --git a/cache.h b/cache.h
index 7257c4c..b50a823 100644
--- a/cache.h
+++ b/cache.h
@@ -259,7 +259,7 @@ extern int write_sha1_from_fd(const unsi
extern int write_sha1_to_fd(int fd, const unsigned char *sha1);
extern int move_temp_to_file(const char *tmpfile, const char *filename);
-extern int has_sha1_pack(const unsigned char *sha1);
+extern int has_sha1_pack(const unsigned char *sha1, const char *ignore);
extern int has_sha1_file(const unsigned char *sha1);
extern void *map_sha1_file(const unsigned char *sha1, unsigned long *);
extern int legacy_loose_object(unsigned char *);
diff --git a/revision.c b/revision.c
index b588f74..fad3b24 100644
--- a/revision.c
+++ b/revision.c
@@ -416,7 +416,8 @@ static void limit_list(struct rev_info *
if (revs->max_age != -1 && (commit->date < revs->max_age))
obj->flags |= UNINTERESTING;
- if (revs->unpacked && has_sha1_pack(obj->sha1))
+ if (revs->unpacked &&
+ has_sha1_pack(obj->sha1, revs->ignore_packed))
obj->flags |= UNINTERESTING;
add_parents_to_list(revs, commit, &list);
if (obj->flags & UNINTERESTING) {
@@ -737,6 +738,12 @@ int setup_revisions(int argc, const char
}
if (!strcmp(arg, "--unpacked")) {
revs->unpacked = 1;
+ revs->ignore_packed = NULL;
+ continue;
+ }
+ if (!strncmp(arg, "--unpacked=", 11)) {
+ revs->unpacked = 1;
+ revs->ignore_packed = arg + 11;
continue;
}
if (!strcmp(arg, "-r")) {
@@ -1046,7 +1053,8 @@ struct commit *get_revision(struct rev_i
*/
if (!revs->limited) {
if ((revs->unpacked &&
- has_sha1_pack(commit->object.sha1)) ||
+ has_sha1_pack(commit->object.sha1,
+ revs->ignore_packed)) ||
(revs->max_age != -1 &&
(commit->date < revs->max_age)))
continue;
diff --git a/revision.h b/revision.h
index d289781..843aeea 100644
--- a/revision.h
+++ b/revision.h
@@ -57,6 +57,9 @@ struct rev_info {
unsigned int shown_one:1,
abbrev_commit:1,
relative_date:1;
+
+ const char *ignore_packed;
+
unsigned int abbrev;
enum cmit_fmt commit_format;
struct log_info *loginfo;
diff --git a/sha1_file.c b/sha1_file.c
index 76f66e6..7031f65 100644
--- a/sha1_file.c
+++ b/sha1_file.c
@@ -1189,12 +1189,15 @@ int find_pack_entry_one(const unsigned c
return 0;
}
-static int find_pack_entry(const unsigned char *sha1, struct pack_entry *e)
+static int find_pack_entry(const unsigned char *sha1,
+ struct pack_entry *e, const char *ignore_packed)
{
struct packed_git *p;
prepare_packed_git();
for (p = packed_git; p; p = p->next) {
+ if (ignore_packed && !strcmp(p->pack_name, ignore_packed))
+ continue;
if (find_pack_entry_one(sha1, e, p))
return 1;
}
@@ -1227,10 +1230,10 @@ int sha1_object_info(const unsigned char
if (!map) {
struct pack_entry e;
- if (find_pack_entry(sha1, &e))
+ if (find_pack_entry(sha1, &e, NULL))
return packed_object_info(&e, type, sizep);
reprepare_packed_git();
- if (find_pack_entry(sha1, &e))
+ if (find_pack_entry(sha1, &e, NULL))
return packed_object_info(&e, type, sizep);
return error("unable to find %s", sha1_to_hex(sha1));
}
@@ -1253,7 +1256,7 @@ static void *read_packed_sha1(const unsi
{
struct pack_entry e;
- if (!find_pack_entry(sha1, &e)) {
+ if (!find_pack_entry(sha1, &e, NULL)) {
error("cannot read sha1_file for %s", sha1_to_hex(sha1));
return NULL;
}
@@ -1266,7 +1269,7 @@ void * read_sha1_file(const unsigned cha
void *map, *buf;
struct pack_entry e;
- if (find_pack_entry(sha1, &e))
+ if (find_pack_entry(sha1, &e, NULL))
return read_packed_sha1(sha1, type, size);
map = map_sha1_file(sha1, &mapsize);
if (map) {
@@ -1275,7 +1278,7 @@ void * read_sha1_file(const unsigned cha
return buf;
}
reprepare_packed_git();
- if (find_pack_entry(sha1, &e))
+ if (find_pack_entry(sha1, &e, NULL))
return read_packed_sha1(sha1, type, size);
return NULL;
}
@@ -1707,10 +1710,10 @@ int has_pack_file(const unsigned char *s
return 1;
}
-int has_sha1_pack(const unsigned char *sha1)
+int has_sha1_pack(const unsigned char *sha1, const char *ignore_packed)
{
struct pack_entry e;
- return find_pack_entry(sha1, &e);
+ return find_pack_entry(sha1, &e, ignore_packed);
}
int has_sha1_file(const unsigned char *sha1)
@@ -1718,7 +1721,7 @@ int has_sha1_file(const unsigned char *s
struct stat st;
struct pack_entry e;
- if (find_pack_entry(sha1, &e))
+ if (find_pack_entry(sha1, &e, NULL))
return 1;
return find_sha1_file(sha1, &st) ? 1 : 0;
}
--
VGER BF report: U 0.5
^ permalink raw reply related
* Re: [PATCH 0/3] git-daemon: plug new upload-tar command
From: Junio C Hamano @ 2006-09-02 10:32 UTC (permalink / raw)
To: Franck Bui-Huu; +Cc: Rene Scharfe, junkio, git
In-Reply-To: <cda58cb80609020114h1e1ee553saf5aa90df8bc3ba0@mail.gmail.com>
"Franck Bui-Huu" <vagabon.xyz@gmail.com> writes:
>> So if you beat me to it, that would be great. Or if you have a better
>> idea, that would be also great. :-)
>
> Well I'll try to start something, not sure to have a lot of time
> though. Please contact me before starting anything, I would be sad to
> write something for /dev/null again ;)
I do not necessarily think your effort were for /dev/null; for
example, I was hoping you defend [PATCH 3/3].
While it makes sense to make "tar-tree --remote" usable outside
a git managed repository, I think people expect the connection
to obey core.gitproxy if the command is run inside a repository
that has a configuration file.
^ permalink raw reply
* Re: [PATCH 0/3] git-daemon: plug new upload-tar command
From: Jakub Narebski @ 2006-09-02 10:36 UTC (permalink / raw)
To: git
In-Reply-To: <7vfyfa1rvf.fsf@assigned-by-dhcp.cox.net>
Junio C Hamano wrote:
> "Franck Bui-Huu" <vagabon.xyz@gmail.com> writes:
>
>>> So if you beat me to it, that would be great. Or if you have a better
>>> idea, that would be also great. :-)
>>
>> Well I'll try to start something, not sure to have a lot of time
>> though. Please contact me before starting anything, I would be sad to
>> write something for /dev/null again ;)
>
> I do not necessarily think your effort were for /dev/null; for
> example, I was hoping you defend [PATCH 3/3].
>
> While it makes sense to make "tar-tree --remote" usable outside
> a git managed repository, I think people expect the connection
> to obey core.gitproxy if the command is run inside a repository
> that has a configuration file.
If I remember correclty git now support (totally undocumented) per-user
configuration file, so one can have core.gitproxy even outside git
repository. Although some warning that you are running from outside
repository and configuration might be not what you want would be nice.
--
Jakub Narebski
Warsaw, Poland
ShadeHawk on #git
^ permalink raw reply
* Re: Mozilla .git tree
From: Shawn Pearce @ 2006-09-02 4:39 UTC (permalink / raw)
To: Junio C Hamano; +Cc: git
In-Reply-To: <7v8xl23oia.fsf@assigned-by-dhcp.cox.net>
Junio C Hamano <junkio@cox.net> wrote:
> So I am inclined to chuck the previous patch that records the
> next object number in each entry. We could keep the 64-bit
> offset, which would make an entry to be 28-byte instead of
> 32-byte.
I can agree with that. :-)
Repacking is infrequent compared to searching for an object.
Asking the repack code to determine object lengths (especially if it
is going to deflate the entry anyway to verify it) isn't that much of
a performance hit. As you pointed out its already happening today.
Using a 28 byte index entry instead of a 32 byte index entry means
the Mozilla historical pack index will only be 52.4 MiB rather than
the slightly larger 59.9 MiB. 1.9x10^6 objects will do that to you.
--
Shawn.
^ permalink raw reply
* Re: Mozilla .git tree
From: Junio C Hamano @ 2006-09-02 11:02 UTC (permalink / raw)
To: Shawn Pearce; +Cc: Nicolas Pitre, git, Linus Torvalds
In-Reply-To: <20060902020426.GF24234@spearce.org>
Shawn Pearce <spearce@spearce.org> writes:
> Junio C Hamano <junkio@cox.net> wrote:
> [snip]
>> +A new style .idx file begins with a signature, "\377tOc", and a
>> +version number as a 4-byte network byte order integer. The version
>> +of this implementation is 2.
>
> Ick. I understand why you did this (and thanks for such a good
> explanation of it by the way) but what a horrible signature number
> and way to wedge in a version number.
I do not think it is particularly horrible.
I initially was planning to introduce a new file extention .toc
(table of contents), not just because that would let us start
afresh with file format that has version number from the
beginning, but also because we use the word "index" to mean
"cache" these days, and it would be a good idea to use a
different word to mean different things. The latter 3 bytes
reflects that.
> I think we probably should have done this when the binary headers
> were introduced into loose objects.
No. That was purely .pack format and did not affect .idx
format. Honestly .idx is purely a local matter and not as
important to keep stable as the .pack format.
> Sure the scheme you outlined allows a 64 bit difference but
> uncompressed objects already can't be larger than 2**32-1...
Where do we have that limitation?
In any case, the next round I am planning to get rid of this
"where the tail is" business. I do not think it buys us much
and inflates the 46MB index you need to deal with even more.
I think your "allow zlib to eat the remainder of the current
window and slide window when it exhausts the current window"
logic is a very good on and makes it unnecessary to know the
tail of each object.
--
VGER BF report: U 0.5
^ permalink raw reply
* Re: Mozilla .git tree
From: Junio C Hamano @ 2006-09-02 11:06 UTC (permalink / raw)
To: Shawn Pearce; +Cc: git
In-Reply-To: <20060902043931.GA25146@spearce.org>
Shawn Pearce <spearce@spearce.org> writes:
> Using a 28 byte index entry instead of a 32 byte index entry means
> the Mozilla historical pack index will only be 52.4 MiB rather than
> the slightly larger 59.9 MiB.
Yup, that was one consideration. One small worry is we will be
placing u64 at 4-byte alignment by using 28-byte entries but I
think that is Ok.
--
VGER BF report: U 0.5
^ permalink raw reply
* [PATCH][RFC] Add git-archive-tree
From: Rene Scharfe @ 2006-09-02 12:23 UTC (permalink / raw)
To: Git Mailing List; +Cc: Junio C Hamano, Franck Bui-Huu
git-archive-tree is a command to make tar and ZIP archives of a git tree.
It helps prevent a proliferation of git-{format}-tree commands. This is
useful e.g. for remote archive fetching because we only need to write a
single upload and a single download program that simply pass on the
format option to git-archive-tree.
Speaking of remote, please note the absence of the --remote option of
git-tar-tree. This is intentional; remote operations are special enough
to deserve a separate (yet to be written) command.
Currently git-archive-tree -f tar is slower than git-tar-tree. This is
because it is welded to the side of the existing code to minimize patch
size, and I also suspect read_tree_recursive() to be quite a bit slower
than builtin-tar-tree.c::traverse_tree().
Documentation/git-archive-tree.txt | 99 +++++++++++++++++++++++++++++++++++++
Makefile | 3 -
archive.h | 6 ++
builtin-archive-tree.c | 92 ++++++++++++++++++++++++++++++++++
builtin-tar-tree.c | 66 ++++++++++++++++++++++++
builtin-zip-tree.c | 28 ++++++++++
builtin.h | 1
git.c | 1
8 files changed, 295 insertions(+), 1 deletion(-)
diff --git a/Documentation/git-archive-tree.txt b/Documentation/git-archive-tree.txt
new file mode 100644
index 0000000..122c482
--- /dev/null
+++ b/Documentation/git-archive-tree.txt
@@ -0,0 +1,99 @@
+git-archive-tree(1)
+===============
+
+NAME
+----
+git-archive-tree - Creates a archive of the files in the named tree
+
+
+SYNOPSIS
+--------
+'git-archive-tree' -f {tar|zip} [--prefix=<prefix>/] [-0|...|-9]
+ <tree-ish> [path...]
+
+DESCRIPTION
+-----------
+Creates an archive of the specified format containing the tree structure
+for the named tree. If <prefix> is specified it is prepended to the
+filenames in the archive.
+
+git-archive-tree behaves differently when given a tree ID versus when
+given a commit ID or tag ID. In the first case the current time is used
+as modification time of each file in the archive. In the latter case the
+commit time as recorded in the referenced commit object is used instead.
+Additionally the commit ID is stored in a global extended pax header if
+the tar format is used; it can be extracted using git-get-tar-commit-id.
+In ZIP files it is stored as a file comment.
+
+OPTIONS
+-------
+
+-f::
+ Format of the resulting archive, can be either 'tar' or 'zip'.
+
+<tree-ish>::
+ The tree or commit to produce an archive for.
+
+path::
+ If one or more paths are specified, include only these in the
+ archive, otherwise include all files and subdirectories.
+
+--prefix=<prefix>/::
+ Prepend <prefix>/ to each filename in the archive.
+
+-0::
+ Store files in the archive instead of compressing them. This
+ option has no effect when the tar format is used.
+
+-9::
+ Highest and slowest compression level. You can specify any
+ number from 1 to 9 to adjust compression speed and ratio. This
+ option has no effect when the tar format is used.
+
+CONFIGURATION
+-------------
+By default, file and directories modes are set to 0666 or 0777 in tar
+archives. It is possible to change this by setting the "umask" variable
+in the repository configuration as follows :
+
+[tar]
+ umask = 002 ;# group friendly
+
+The special umask value "user" indicates that the user's current umask
+will be used instead. The default value remains 0, which means world
+readable/writable files and directories.
+
+EXAMPLES
+--------
+git archive -f tar --prefix=junk/ HEAD | (cd /var/tmp/ && tar xf -)::
+
+ Create a tar archive that contains the contents of the
+ latest commit on the current branch, and extracts it in
+ `/var/tmp/junk` directory.
+
+git archive -f tar --prefix=git-1.4.0/ v1.4.0 | gzip >git-1.4.0.tar.gz::
+
+ Create a compressed tarball for v1.4.0 release.
+
+git archive -f tar --prefix=git-1.4.0/ v1.4.0{caret}\{tree\} | gzip >git-1.4.0.tar.gz::
+
+ Create a compressed tarball for v1.4.0 release, but without a
+ global extended pax header.
+
+git archive -f zip --prefix=git-docs/ HEAD:Documentation/ > git-1.4.0-docs.zip::
+
+ Put everything in the current head's Documentation/ directory
+ into 'git-1.4.0-docs.zip', with the prefix 'git-docs/'.
+
+Author
+------
+Written by Rene Scharfe.
+
+Documentation
+--------------
+Documentation by David Greaves, Junio C Hamano and the git-list <git@vger.kernel.org>.
+
+GIT
+---
+Part of the gitlink:git[7] suite
+
diff --git a/Makefile b/Makefile
index 05bd77f..d0a1055 100644
--- a/Makefile
+++ b/Makefile
@@ -231,7 +231,7 @@ LIB_FILE=libgit.a
XDIFF_LIB=xdiff/lib.a
LIB_H = \
- blob.h cache.h commit.h csum-file.h delta.h \
+ archive.h blob.h cache.h commit.h csum-file.h delta.h \
diff.h object.h pack.h pkt-line.h quote.h refs.h \
run-command.h strbuf.h tag.h tree.h git-compat-util.h revision.h \
tree-walk.h log-tree.h dir.h path-list.h unpack-trees.h builtin.h
@@ -255,6 +255,7 @@ LIB_OBJS = \
BUILTIN_OBJS = \
builtin-add.o \
builtin-apply.o \
+ builtin-archive-tree.o \
builtin-cat-file.o \
builtin-checkout-index.o \
builtin-check-ref-format.o \
diff --git a/archive.h b/archive.h
new file mode 100644
index 0000000..7813962
--- /dev/null
+++ b/archive.h
@@ -0,0 +1,6 @@
+#include "tree.h"
+
+typedef int (*write_archive_fn_t)(struct tree *tree, const unsigned char *commit_sha1, const char *prefix, time_t time, const char **pathspec);
+
+int write_tar_archive(struct tree *tree, const unsigned char *commit_sha1, const char *prefix, time_t time, const char **pathspec);
+int write_zip_archive(struct tree *tree, const unsigned char *commit_sha1, const char *prefix, time_t time, const char **pathspec);
diff --git a/builtin-archive-tree.c b/builtin-archive-tree.c
new file mode 100644
index 0000000..2c6ee60
--- /dev/null
+++ b/builtin-archive-tree.c
@@ -0,0 +1,92 @@
+/*
+ * Copyright (c) 2006 Rene Scharfe
+ */
+#include <time.h>
+#include "cache.h"
+#include "builtin.h"
+#include "commit.h"
+#include "tree-walk.h"
+#include "archive.h"
+
+static const char archive_usage[] =
+"git-archive-tree -f {tar|zip} [--prefix=<prefix>/] [-0|...|-9] <tree-ish> [path...]";
+
+static write_archive_fn_t parse_archive_format(const char *format)
+{
+ if (!strcmp(format, "tar"))
+ return write_tar_archive;
+ if (!strcmp(format, "zip"))
+ return write_zip_archive;
+ return NULL;
+}
+
+int cmd_archive_tree(int argc, const char **argv, const char *prefix)
+{
+ int more_args = 1;
+ const char *archive_prefix = "";
+ unsigned char sha1[20];
+ struct commit *commit;
+ time_t archive_time;
+ const char **pathspec;
+ const unsigned char *commit_sha1 = NULL;
+ write_archive_fn_t write_archive = NULL;
+ struct tree *tree;
+ int result;
+
+ while (argc > 2 && more_args) {
+ const char *arg = argv[1];
+ if (!strcmp(arg, "-f")) {
+ write_archive = parse_archive_format(argv[2]);
+ argv++;
+ argc--;
+ } else if (!strncmp(arg, "-f", 2))
+ write_archive = parse_archive_format(arg + 2);
+ else if (arg[0] == '-' && isdigit(arg[1]) && arg[2] == '\0')
+ zlib_compression_level = arg[1] - '0';
+ else if (!strcmp(arg, "--"))
+ more_args = 0;
+ else if (!strncmp(arg, "--prefix=", 9))
+ archive_prefix = arg + 9;
+ else if (arg[0] == '-')
+ usage(archive_usage);
+ else
+ break;
+ argv++;
+ argc--;
+ }
+
+ if (!write_archive)
+ usage(archive_usage);
+ if (argc < 2)
+ usage(archive_usage);
+ if (get_sha1(argv[1], sha1))
+ die("Not a valid object name %s", argv[1]);
+
+ commit = lookup_commit_reference_gently(sha1, 1);
+ if (commit)
+ commit_sha1 = commit->object.sha1;
+
+ tree = parse_tree_indirect(sha1);
+ if (!tree)
+ die("not a tree object");
+
+ if (prefix) {
+ unsigned char tree_sha1[20];
+ unsigned int mode;
+ int err = get_tree_entry(tree->object.sha1, prefix,
+ tree_sha1, &mode);
+ if (err || !S_ISDIR(mode))
+ die("current working directory is untracked");
+ free(tree);
+ tree = parse_tree_indirect(tree_sha1);
+ }
+
+ archive_time = commit ? commit->date : time(NULL);
+ pathspec = get_pathspec(archive_prefix, argv + 2);
+
+ result = write_archive(tree, commit_sha1, archive_prefix,
+ archive_time, pathspec);
+ free(tree);
+
+ return result;
+}
diff --git a/builtin-tar-tree.c b/builtin-tar-tree.c
index 61a4135..e0da01e 100644
--- a/builtin-tar-tree.c
+++ b/builtin-tar-tree.c
@@ -9,6 +9,7 @@ #include "strbuf.h"
#include "tar.h"
#include "builtin.h"
#include "pkt-line.h"
+#include "archive.h"
#define RECORDSIZE (512)
#define BLOCKSIZE (RECORDSIZE * 20)
@@ -338,6 +339,71 @@ static int generate_tar(int argc, const
return 0;
}
+static int write_tar_entry(const unsigned char *sha1,
+ const char *base, int baselen,
+ const char *filename, unsigned mode, int stage)
+{
+ static struct strbuf path;
+ int filenamelen = strlen(filename);
+ void *buffer;
+ char type[20];
+ unsigned long size;
+
+ if (!path.alloc) {
+ path.buf = xmalloc(PATH_MAX);
+ path.alloc = PATH_MAX;
+ path.len = path.eof = 0;
+ }
+ if (path.alloc < baselen + filenamelen) {
+ free(path.buf);
+ path.buf = xmalloc(baselen + filenamelen);
+ path.alloc = baselen + filenamelen;
+ }
+ memcpy(path.buf, base, baselen);
+ memcpy(path.buf + baselen, filename, filenamelen);
+ path.len = baselen + filenamelen;
+ if (S_ISDIR(mode)) {
+ strbuf_append_string(&path, "/");
+ buffer = NULL;
+ size = 0;
+ } else {
+ buffer = read_sha1_file(sha1, type, &size);
+ if (!buffer)
+ die("cannot read %s", sha1_to_hex(sha1));
+ }
+
+ write_entry(sha1, &path, mode, buffer, size);
+
+ return READ_TREE_RECURSIVE;
+}
+
+int write_tar_archive(struct tree *tree, const unsigned char *commit_sha1,
+ const char *prefix, time_t time, const char **pathspec)
+{
+ int plen = strlen(prefix);
+
+ git_config(git_tar_config);
+
+ archive_time = time;
+
+ if (commit_sha1)
+ write_global_extended_header(commit_sha1);
+
+ if (prefix && plen > 0 && prefix[plen - 1] == '/') {
+ char *base = strdup(prefix);
+ int baselen = strlen(base);
+
+ while (baselen > 0 && base[baselen - 1] == '/')
+ base[--baselen] = '\0';
+ write_tar_entry(tree->object.sha1, "", 0, base, 040777, 0);
+ free(base);
+ }
+ read_tree_recursive(tree, prefix, plen, 0, pathspec, write_tar_entry);
+ write_trailer();
+
+ return 0;
+}
+
static const char *exec = "git-upload-tar";
static int remote_tar(int argc, const char **argv)
diff --git a/builtin-zip-tree.c b/builtin-zip-tree.c
index a5b834d..b142771 100644
--- a/builtin-zip-tree.c
+++ b/builtin-zip-tree.c
@@ -8,6 +8,7 @@ #include "blob.h"
#include "tree.h"
#include "quote.h"
#include "builtin.h"
+#include "archive.h"
static const char zip_tree_usage[] =
"git-zip-tree [-0|...|-9] <tree-ish> [ <base> ]";
@@ -351,3 +352,30 @@ int cmd_zip_tree(int argc, const char **
return 0;
}
+
+int write_zip_archive(struct tree *tree, const unsigned char *commit_sha1,
+ const char *prefix, time_t time, const char **pathspec)
+{
+ int plen = strlen(prefix);
+
+ dos_time(&time, &zip_date, &zip_time);
+
+ zip_dir = xmalloc(ZIP_DIRECTORY_MIN_SIZE);
+ zip_dir_size = ZIP_DIRECTORY_MIN_SIZE;
+
+ if (prefix && plen > 0 && prefix[plen - 1] == '/') {
+ char *base = strdup(prefix);
+ int baselen = strlen(base);
+
+ while (baselen > 0 && base[baselen - 1] == '/')
+ base[--baselen] = '\0';
+ write_zip_entry(tree->object.sha1, "", 0, base, 040777, 0);
+ free(base);
+ }
+ read_tree_recursive(tree, prefix, plen, 0, pathspec, write_zip_entry);
+ write_zip_trailer(commit_sha1);
+
+ free(zip_dir);
+
+ return 0;
+}
diff --git a/builtin.h b/builtin.h
index 25431d7..febb9d0 100644
--- a/builtin.h
+++ b/builtin.h
@@ -53,6 +53,7 @@ extern int cmd_stripspace(int argc, cons
extern int cmd_symbolic_ref(int argc, const char **argv, const char *prefix);
extern int cmd_tar_tree(int argc, const char **argv, const char *prefix);
extern int cmd_zip_tree(int argc, const char **argv, const char *prefix);
+extern int cmd_archive_tree(int argc, const char **argv, const char *prefix);
extern int cmd_unpack_objects(int argc, const char **argv, const char *prefix);
extern int cmd_update_index(int argc, const char **argv, const char *prefix);
extern int cmd_update_ref(int argc, const char **argv, const char *prefix);
diff --git a/git.c b/git.c
index 05871ad..937b7f7 100644
--- a/git.c
+++ b/git.c
@@ -264,6 +264,7 @@ static void handle_internal_command(int
{ "symbolic-ref", cmd_symbolic_ref, RUN_SETUP },
{ "tar-tree", cmd_tar_tree, RUN_SETUP },
{ "zip-tree", cmd_zip_tree, RUN_SETUP },
+ { "archive-tree", cmd_archive_tree, RUN_SETUP },
{ "unpack-objects", cmd_unpack_objects, RUN_SETUP },
{ "update-index", cmd_update_index, RUN_SETUP },
{ "update-ref", cmd_update_ref, RUN_SETUP },
--
VGER BF report: U 0.5
^ permalink raw reply related
* [PATCH] Add support for tgz archive format
From: Rene Scharfe @ 2006-09-02 12:37 UTC (permalink / raw)
To: Git Mailing List; +Cc: Junio C Hamano, Franck Bui-Huu
In-Reply-To: <44F977C0.4060901@lsrfire.ath.cx>
Documentation/git-archive-tree.txt | 9 ++---
archive.h | 2 +
builtin-archive-tree.c | 4 +-
builtin-tar-tree.c | 63 ++++++++++++++++++++++++++++++++-----
4 files changed, 65 insertions(+), 13 deletions(-)
diff --git a/Documentation/git-archive-tree.txt b/Documentation/git-archive-tree.txt
index 122c482..25136d9 100644
--- a/Documentation/git-archive-tree.txt
+++ b/Documentation/git-archive-tree.txt
@@ -8,7 +8,7 @@ git-archive-tree - Creates a archive of the f
SYNOPSIS
--------
-'git-archive-tree' -f {tar|zip} [--prefix=<prefix>/] [-0|...|-9]
+'git-archive-tree' -f {tar|tgz|zip} [--prefix=<prefix>/] [-0|...|-9]
<tree-ish> [path...]
DESCRIPTION
@@ -29,7 +29,8 @@ OPTIONS
-------
-f::
- Format of the resulting archive, can be either 'tar' or 'zip'.
+ Format of the resulting archive, can be either 'tar', 'tgz'
+ or 'zip'.
<tree-ish>::
The tree or commit to produce an archive for.
@@ -71,11 +72,11 @@ git archive -f tar --prefix=junk/ HEAD |
latest commit on the current branch, and extracts it in
`/var/tmp/junk` directory.
-git archive -f tar --prefix=git-1.4.0/ v1.4.0 | gzip >git-1.4.0.tar.gz::
+git archive -f tgz --prefix=git-1.4.0/ v1.4.0 >git-1.4.0.tar.gz::
Create a compressed tarball for v1.4.0 release.
-git archive -f tar --prefix=git-1.4.0/ v1.4.0{caret}\{tree\} | gzip >git-1.4.0.tar.gz::
+git archive -f tgz --prefix=git-1.4.0/ v1.4.0{caret}\{tree\} >git-1.4.0.tar.gz::
Create a compressed tarball for v1.4.0 release, but without a
global extended pax header.
diff --git a/archive.h b/archive.h
index 7813962..6a03864 100644
--- a/archive.h
+++ b/archive.h
@@ -3,4 +3,6 @@ #include "tree.h"
typedef int (*write_archive_fn_t)(struct tree *tree, const unsigned char *commit_sha1, const char *prefix, time_t time, const char **pathspec);
int write_tar_archive(struct tree *tree, const unsigned char *commit_sha1, const char *prefix, time_t time, const char **pathspec);
+int write_tgz_archive(struct tree *tree, const unsigned char *commit_sha1,
+ const char *prefix, time_t time, const char **pathspec);
int write_zip_archive(struct tree *tree, const unsigned char *commit_sha1, const char *prefix, time_t time, const char **pathspec);
diff --git a/builtin-archive-tree.c b/builtin-archive-tree.c
index 2c6ee60..f61e26d 100644
--- a/builtin-archive-tree.c
+++ b/builtin-archive-tree.c
@@ -9,12 +9,14 @@ #include "tree-walk.h"
#include "archive.h"
static const char archive_usage[] =
-"git-archive-tree -f {tar|zip} [--prefix=<prefix>/] [-0|...|-9] <tree-ish> [path...]";
+"git-archive-tree -f {tar|tgz|zip} [--prefix=<prefix>/] [-0|...|-9] <tree-ish> [path...]";
static write_archive_fn_t parse_archive_format(const char *format)
{
if (!strcmp(format, "tar"))
return write_tar_archive;
+ if (!strcmp(format, "tgz"))
+ return write_tgz_archive;
if (!strcmp(format, "zip"))
return write_zip_archive;
return NULL;
diff --git a/builtin-tar-tree.c b/builtin-tar-tree.c
index e0da01e..743d53a 100644
--- a/builtin-tar-tree.c
+++ b/builtin-tar-tree.c
@@ -23,6 +23,10 @@ static unsigned long offset;
static time_t archive_time;
static int tar_umask;
+static gzFile gzstdout;
+
+typedef void (*blocked_write_fn)(const void *data, unsigned long size);
+
/* writes out the whole block, but only if it is full */
static void write_if_needed(void)
{
@@ -36,7 +40,7 @@ static void write_if_needed(void)
* queues up writes, so that all our write(2) calls write exactly one
* full block; pads writes to RECORDSIZE
*/
-static void write_blocked(const void *data, unsigned long size)
+static void do_write_blocked(const void *data, unsigned long size)
{
const char *buf = data;
unsigned long tail;
@@ -68,19 +72,20 @@ static void write_blocked(const void *da
write_if_needed();
}
+static blocked_write_fn write_blocked = do_write_blocked;
+
/*
* The end of tar archives is marked by 2*512 nul bytes and after that
* follows the rest of the block (if any).
*/
static void write_trailer(void)
{
- int tail = BLOCKSIZE - offset;
- memset(block + offset, 0, tail);
- write_or_die(1, block, BLOCKSIZE);
- if (tail < 2 * RECORDSIZE) {
- memset(block, 0, offset);
- write_or_die(1, block, BLOCKSIZE);
- }
+ char zeroes[RECORDSIZE];
+ memset(zeroes, 0, RECORDSIZE);
+ write_blocked(zeroes, RECORDSIZE);
+ write_blocked(zeroes, RECORDSIZE);
+ while (offset)
+ write_blocked(zeroes, RECORDSIZE);
}
static void strbuf_append_string(struct strbuf *sb, const char *s)
@@ -404,6 +409,48 @@ int write_tar_archive(struct tree *tree,
return 0;
}
+static void write_blocked_gzip(const void *data, unsigned long size)
+{
+ const char *p = data;
+ int written;
+ unsigned long tail = size % RECORDSIZE;
+
+ while (size > 0) {
+ written = gzwrite(gzstdout, p, size);
+ if (written == 0) {
+ if (errno == EPIPE)
+ exit(0);
+ die("gzwrite error (%s)", strerror(errno));
+ }
+ size -= written;
+ p += written;
+ }
+
+ if (tail) {
+ z_off_t result = gzseek(gzstdout, RECORDSIZE - tail, SEEK_CUR);
+ if (result == -1)
+ die("gzseek error (%s)", strerror(errno));
+ }
+}
+
+int write_tgz_archive(struct tree *tree, const unsigned char *commit_sha1,
+ const char *prefix, time_t time, const char **pathspec)
+{
+ int result;
+
+ gzstdout = gzdopen(1, "wb");
+ if (!gzstdout)
+ die("zlib is unable to open stdout");
+
+ write_blocked = write_blocked_gzip;
+ result = write_tar_archive(tree, commit_sha1, prefix, time, pathspec);
+
+ if (gzclose(gzstdout) != Z_OK)
+ result = 1;
+
+ return result;
+}
+
static const char *exec = "git-upload-tar";
static int remote_tar(int argc, const char **argv)
--
VGER BF report: U 0.497484
^ permalink raw reply related
* Re: [PATCH][RFC] Add git-archive-tree
From: Rene Scharfe @ 2006-09-02 13:10 UTC (permalink / raw)
To: Git Mailing List; +Cc: Junio C Hamano, Franck Bui-Huu
In-Reply-To: <44F977C0.4060901@lsrfire.ath.cx>
The two patches I sent are what I have been able to come up with so far.
The next step would be to add archive-neutral upload and download support.
Having thought a bit about it I propose to keep git-archive-tree for
local operations, only. It can be called by the uploader just like
git-tar-tree is now called by git-upload-tar. As Franck suggested, the
uploader should allow the list of archive formats it supports to be
restricted in a config file. The range of allowed compression levels
should also be configurable.
Does it make sense to change the wire protocol to simply send the
command line options one by one?
The interface could be something like this:
git-download-archive <repo> <git-archive-tree options...>
git-upload-archive <directory>
Or, if the big number of git command names is a concern:
git-archive-remote --upload|--download ...
What do you all think?
I won't have time for any of this over the next few days, so Franck, go
wild. ;-)
René
--
VGER BF report: U 0.499999
^ permalink raw reply
* Re: [PATCH][RFC] Add git-archive-tree
From: Rene Scharfe @ 2006-09-02 14:17 UTC (permalink / raw)
To: Git Mailing List; +Cc: Junio C Hamano, Franck Bui-Huu
In-Reply-To: <44F977C0.4060901@lsrfire.ath.cx>
Oops, forgot to sign off. Please consider both patches
(git-archive-tree and tgz support) as
Signed-off-by: Rene Scharfe <rene.scharfe@lsrfire.ath.cx>
--
VGER BF report: U 0.500007
^ permalink raw reply
* Re: Mozilla .git tree
From: Jon Smirl @ 2006-09-02 14:20 UTC (permalink / raw)
To: Junio C Hamano; +Cc: Shawn Pearce, git
In-Reply-To: <7vveo6zfx0.fsf@assigned-by-dhcp.cox.net>
On 9/2/06, Junio C Hamano <junkio@cox.net> wrote:
> Shawn Pearce <spearce@spearce.org> writes:
>
> > Using a 28 byte index entry instead of a 32 byte index entry means
> > the Mozilla historical pack index will only be 52.4 MiB rather than
> > the slightly larger 59.9 MiB.
>
> Yup, that was one consideration. One small worry is we will be
> placing u64 at 4-byte alignment by using 28-byte entries but I
> think that is Ok.
If you're going to redo the pack formats another big win for the
Mozilla pack is to convert pack internal sha1 references into file
offsets.within the pack. Doing that will take around 30MB off from the
Mozilla pack size. sha1's are not compressible so this is a direct
savings.
This might reduce memory usage too. The index is only needed to get
the initial object from the pack. Since index use is lighter it could
just be open/closed when needed.
You could also introduce a zlib dictionary object into the format and
just leave it empty for now.
--
Jon Smirl
jonsmirl@gmail.com
--
VGER BF report: U 0.5
^ permalink raw reply
* Mozilla version control requirements and git
From: Jon Smirl @ 2006-09-02 14:31 UTC (permalink / raw)
To: git
The Mozilla people have a web page describing what they are looking
for in a new version control system. How does git stack up?
http://wiki.mozilla.org/Version_Control_System_Requirements
They have also recently put up a Subversion server for limited use.
http://weblogs.mozillazine.org/preed/2006/08/subversive_subversion_conversi.html
--
Jon Smirl
jonsmirl@gmail.com
--
VGER BF report: U 0.506426
^ permalink raw reply
* Suggestions for my use case
From: Russell @ 2006-09-02 14:41 UTC (permalink / raw)
To: git
Hello,
I've been tring git for a few private projects and have come up with a
way to organise distributed development on multiple machines. I was
wondering if anyone else could comment on what I've done? Here it
is...
I want to be able to work on a project called proj on multiple
computers, and have backups on removable media. Let's say I have
computers c1 and c2, and a removable hard disk labelled disk1. I've
setup the repositories in
c1: /home/me/proj
c2: /home/me/proj
disk1: /media/disk1/me/proj
In c1:/home/me/proj/.git/remotes/c2
URL: ssh://c2/home/me/proj
Pull: refs/heads/master:refs/heads/host/c2
Push: refs/heads/master:refs/heads/host/c1
In c1:/home/me/proj/.git/remotes/disk1
URL: /media/disk1/me/proj
Pull: refs/heads/master:refs/heads/disk/disk1
Push: refs/heads/master:refs/heads/host/c1
In c2:/home/me/proj/.git/remotes/c1
URL: ssh://c1/home/me/proj
Pull: refs/heads/master:refs/heads/host/c1
Push: refs/heads/master:refs/heads/host/c2
In c2:/home/me/proj/.git/remotes/disk1
URL: /media/disk1/me/proj
Pull: refs/heads/master:refs/heads/disk/disk1
Push: refs/heads/master:refs/heads/host/c2
c1 has these branches:
master
host/c2
disk/disk1
c2 has these branches:
master
host/c1
disk/disk1
disk1 has these branches:
master
host/c1
host/c2
So after doing some work at c1 and committing into master, I can
c1$ git-push c2
c1$ git-push disk1
Then when I sit down at c2:
c2$ git-pull . host/c1
Or if I've forgotten to push from c1:
c2$ git-pull c1
Or I can cart disk1 around, and
c2$ git-pull disk1
Each repository stays on its master branch. As per the git-pull man
page, no development is done on branches that I pull from.
This is working fine for me at the moment, which is single person
development, straight line, no branching. When I come to branches, I
think the branches will need to be added in each repository, with push
and pull lines in .git/remotes/c1 etc.
Does this look reasonable? What have I missed that would make this
more manageable, particularly with respect to branching?
--
VGER BF report: U 0.500329
^ permalink raw reply
* Re: [PATCH][RFC] Add git-archive-tree
From: Franck Bui-Huu @ 2006-09-02 15:24 UTC (permalink / raw)
To: Rene Scharfe; +Cc: Git Mailing List, Junio C Hamano
In-Reply-To: <44F977C0.4060901@lsrfire.ath.cx>
Hi,
2006/9/2, Rene Scharfe <rene.scharfe@lsrfire.ath.cx>:
> git-archive-tree is a command to make tar and ZIP archives of a git tree.
> It helps prevent a proliferation of git-{format}-tree commands. This is
> useful e.g. for remote archive fetching because we only need to write a
> single upload and a single download program that simply pass on the
> format option to git-archive-tree.
OK, Rene you beat me. I started to cook up something this morning but
had no time to go further.
I sent a starting implementation just because it seems complementary
to the one you sent a couple hours ago: it supports '--remote' option.
But it does _not_ have path spec support you introduced. I think it's
cool feature but I would have to dig into git's internal to implement
it, which would have taken me a while.
>From now, do you think we should import my work into your version or
'vice verca' ?
-- >8 --
Subject: [PATCH] Add git-archive (other implementation)
Signed-off-by: Franck Bui-Huu <vagabon.xyz@gmail.com>
---
.gitignore | 1
Makefile | 1
builtin-archive.c | 171 +++++++++++++++++++++++++++++++++++++++++++++++++++
builtin.h | 1
generate-cmdlist.sh | 1
git.c | 1
6 files changed, 176 insertions(+), 0 deletions(-)
diff --git a/.gitignore b/.gitignore
index 78cb671..a3e7ca1 100644
--- a/.gitignore
+++ b/.gitignore
@@ -8,6 +8,7 @@ git-apply
git-applymbox
git-applypatch
git-archimport
+git-archive
git-bisect
git-branch
git-cat-file
diff --git a/Makefile b/Makefile
index 164dbcf..8d963e0 100644
--- a/Makefile
+++ b/Makefile
@@ -266,6 +266,7 @@ LIB_OBJS = \
BUILTIN_OBJS = \
builtin-add.o \
builtin-apply.o \
+ builtin-archive.o \
builtin-cat-file.o \
builtin-checkout-index.o \
builtin-check-ref-format.o \
diff --git a/builtin-archive.c b/builtin-archive.c
new file mode 100644
index 0000000..47898ee
--- /dev/null
+++ b/builtin-archive.c
@@ -0,0 +1,171 @@
+/*
+ * Copyright (c) 2006 Franck Bui-Huu
+ */
+#include "cache.h"
+#include "builtin.h"
+#include "exec_cmd.h"
+#include "pkt-line.h"
+
+#define MAX_ARGS 32
+
+static const char *extra_argv[MAX_ARGS];
+static int extra_argc = 1;
+static const char *base;
+static const char *remote;
+
+static const char archive_usage[] = \
+"git-archive -f <format> [extra] [--remote=<repo>] [--prefix=<base>]
<tree-ish>";
+
+/* archiver's options */
+#define NEED_BASE (1<<0)
+
+struct archiver_info {
+ const char *name;
+ int (*fn)(int argc, const char **argv, const char *prefix);
+ int options;
+};
+
+static struct archiver_info archivers[] = {
+ { "tar", cmd_tar_tree, NEED_BASE },
+ { "zip", cmd_zip_tree, NEED_BASE },
+};
+
+static int run_remote_archiver(struct archiver_info *ar, char *url)
+{
+ int fd[2], len, rv;
+ char buf[1024];
+ pid_t pid;
+
+ /*
+ * For now, remote operations does not support extra options
+ */
+ if (extra_argc > 2)
+ die("Remote operation does not support extra options yet.");
+
+ sprintf(buf, "git-upload-%s", ar->name);
+ pid = git_connect(fd, url, buf);
+ if (pid < 0)
+ return pid;
+
+ packet_write(fd[1], "want %s\n", extra_argv[1]);
+ if (base)
+ packet_write(fd[1], "base %s\n", base);
+ packet_flush(fd[1]);
+
+ len = packet_read_line(fd[0], buf, sizeof(buf));
+ if (!len)
+ die("git-archive: expected ACK/NAK, got EOF");
+ if (buf[len-1] == '\n')
+ buf[--len] = 0;
+ if (strcmp(buf, "ACK")) {
+ if (len > 5 && !strncmp(buf, "NACK ", 5))
+ die("git-archive: NACK %s", buf + 5);
+ die("git-archive: protocol error");
+ }
+ if (packet_read_line(fd[0], buf, sizeof(buf)))
+ die("git-archive: expected a flush");
+
+ /* Now, start reading from fd[0] and spit it out to stdout */
+ rv = copy_fd(fd[0], 1);
+ close(fd[0]);
+
+ return !!(rv | finish_connect(pid));
+}
+
+void insert_extra_option(const char *option, int idx)
+{
+ const char **argv = extra_argv; /* some shortcuts... */
+ int argc = extra_argc;
+
+ if (argc > MAX_ARGS - 2)
+ die("Too many args");
+ if (idx > MAX_ARGS - 1)
+ die("idx overflow extra_argv buffer !");
+
+ /* insert at last position ? */
+ if (idx < 0) {
+ argv[argc++] = option;
+ argv[argc] = NULL;
+ } else {
+ argv += idx;
+ memmove(argv + 1, argv, argc * sizeof(*argv));
+ *argv = option;
+ }
+ extra_argc++;
+}
+
+int run_archiver(const char *format)
+{
+ struct archiver_info *ar;
+ char buf[32];
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(archivers); i++) {
+ ar = &archivers[i];
+ if (strcmp(format, ar->name))
+ continue;
+ goto found;
+ }
+ return error("Unknown archive format '%s'\n", format);
+found:
+ if (remote) {
+ char *url = strdup(remote+9); /* --remote=<repo> */
+ return run_remote_archiver(ar, url);
+ }
+ if (base) {
+ i = 1;
+ if (ar->options & NEED_BASE) {
+ base += 9; /* --prefix=<base> */
+ i = -1;
+ }
+ insert_extra_option(base, i);
+ }
+ sprintf(buf, "%s-tree", ar->name);
+ extra_argv[0] = buf;
+
+ return ar->fn(extra_argc, extra_argv, setup_git_directory());
+}
+
+static int show_list_formats(void)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(archivers); i++) {
+ printf("%s\n", archivers[i].name);
+ }
+ return 0;
+}
+
+int cmd_archive(int argc, const char **argv, const char *prefix)
+{
+ static const char *format;
+ int i;
+
+ for (i = 1; i < argc; i++) {
+ const char *arg = argv[i];
+
+ if (!strcmp(arg, "--list") || !strcmp(arg, "-l")) {
+ return show_list_formats();
+ }
+ if (!strncmp(arg, "--format=", 9)) {
+ format = arg+9;
+ continue;
+ }
+ if (!strncmp(arg, "--prefix=", 9)) {
+ base = arg;
+ continue;
+ }
+ if (!strncmp(arg, "--remote=", 9)) {
+ remote = arg;
+ continue;
+ }
+ if (extra_argc > MAX_ARGS - 2)
+ die("Too many options");
+ extra_argv[extra_argc++] = arg;
+ }
+
+ if (!format)
+ die("You must specify an archive format");
+
+ return run_archiver(format);
+}
diff --git a/builtin.h b/builtin.h
index 25431d7..50852cd 100644
--- a/builtin.h
+++ b/builtin.h
@@ -15,6 +15,7 @@ extern int write_tree(unsigned char *sha
extern int cmd_add(int argc, const char **argv, const char *prefix);
extern int cmd_apply(int argc, const char **argv, const char *prefix);
+extern int cmd_archive(int argc, const char **argv, const char *prefix);
extern int cmd_cat_file(int argc, const char **argv, const char *prefix);
extern int cmd_checkout_index(int argc, const char **argv, const char *prefix);
extern int cmd_check_ref_format(int argc, const char **argv, const
char *prefix);
diff --git a/generate-cmdlist.sh b/generate-cmdlist.sh
index ec1eda2..5450918 100755
--- a/generate-cmdlist.sh
+++ b/generate-cmdlist.sh
@@ -12,6 +12,7 @@ struct cmdname_help common_cmds[] = {"
sort <<\EOF |
add
apply
+archive
bisect
branch
checkout
diff --git a/git.c b/git.c
index 403fb3a..ddb1620 100644
--- a/git.c
+++ b/git.c
@@ -218,6 +218,7 @@ static void handle_internal_command(int
} commands[] = {
{ "add", cmd_add, RUN_SETUP },
{ "apply", cmd_apply },
+ { "archive", cmd_archive },
{ "cat-file", cmd_cat_file, RUN_SETUP },
{ "checkout-index", cmd_checkout_index, RUN_SETUP },
{ "check-ref-format", cmd_check_ref_format },
--
1.4.2.g8ed9-dirty
--
VGER BF report: U 0.5
^ permalink raw reply related
* Slightly offtopic: Windows Explorer extension
From: Johannes Schindelin @ 2006-09-02 15:38 UTC (permalink / raw)
To: git
[-- Attachment #1: Type: TEXT/PLAIN, Size: 1106 bytes --]
Hi,
a couple of weeks ago, I started to port git to MinGW, with the ultimate
goal of writing a Windows Explorer extension a la TortoiseCVS.
The two biggest obstacles are fork() and the network stuff (I do not plan
on supporting Git.pm there). To overcome the absence of fork() I wanted to
use the subprocess stuff in MinGW's port of GNU make.
Unfortunately, this effort was stalled a bit: I got side-tracked by the
Windows Explorer extension mechanism. I found it really exciting (in the
sense of an Arcade game end-of-level monster) to find a way to _easily_
write a Windows Explorer extension. Without cashware.
Since the extensions are a very substantial part of Windows Explorer, one
might guess that it is relatively simple to write one. Ha! COM!
Attached is my (unfortunately stalled) WIP of such an extension. You need
MinGW to compile it. It adds a menu entry "Hallo Dan de Man" to the
Explorer context menu. If you select it, it just shows an alert box with
the current file/directory name.
I'll be gone for one week, so if anyone wants to pick up the ball, go
wild.
Ciao,
Dscho
[-- Attachment #2: Type: APPLICATION/x-gunzip, Size: 3412 bytes --]
^ permalink raw reply
* Re: [PATCH][RFC] Add git-archive-tree
From: Rene Scharfe @ 2006-09-02 16:08 UTC (permalink / raw)
To: Franck Bui-Huu; +Cc: Git Mailing List, Junio C Hamano
In-Reply-To: <cda58cb80609020824ja524444uc9fe65ea2e4febba@mail.gmail.com>
Franck Bui-Huu schrieb:
> Hi,
>
> 2006/9/2, Rene Scharfe <rene.scharfe@lsrfire.ath.cx>:
>> git-archive-tree is a command to make tar and ZIP archives of a git tree.
>> It helps prevent a proliferation of git-{format}-tree commands. This is
>> useful e.g. for remote archive fetching because we only need to write a
>> single upload and a single download program that simply pass on the
>> format option to git-archive-tree.
>
> OK, Rene you beat me. I started to cook up something this morning but
> had no time to go further.
I am sorry. My excuse is I was so angry the other night (for unrelated
reasons) that I started coding and I didn't stop until git-archive-tree
was working at three in the morning.
> I sent a starting implementation just because it seems complementary
> to the one you sent a couple hours ago: it supports '--remote' option.
> But it does _not_ have path spec support you introduced. I think it's
> cool feature but I would have to dig into git's internal to implement
> it, which would have taken me a while.
I cheated by using the already existing function read_tree_recursive().
> From now, do you think we should import my work into your version or
> 'vice verca' ?
Of course I like mine better. :-) But first we need to agree on a
direction. I think it makes sense to keep the network stuff out of the
archiver, and to keep the downloader as simple ("dumb") as possible: it
should pass on any options unaltered, including the format option.
That means the wire format changes completely, but since this feature
hasn't been officially released, yet, this shouldn't be a problem, right?
So, I propose to not add anything (except new formats) to
git-archive-tree and to add a separate downloader and uploader (maybe
combined in one program) instead. That way the remote archive
operations are format agnostic. OK, almost, because the uploader needs
to determine the format and compression level in order to allow or
disallow uploads based on that.
What do you think?
Thanks,
René
--
VGER BF report: U 0.539485
^ permalink raw reply
* [RFC] gitweb wishlist and TODO list
From: Jakub Narebski @ 2006-09-02 16:17 UTC (permalink / raw)
To: git
This is second series of planned gitweb features. Still ideas for many
of them come from xmms2's gitweb version, which can you see in work at
http://git.xmms.se/?p=gitweb-xmms2.git;a=summary
Some of gitweb features like snapshot support and clone/fetch URL were
implemented, some of cleanup like refactoring navbar generation or
putting CSS into separate style file too.
I have put the list here for three reasons. First to get input which
features are most wanted, and to receive perhaps ideas for new
features. Second, to have TODO list, and receive input if somebody is
doing implementing some of the features to avoid duplicate work. Third,
and most important, some of features needs discussion about _how_ to
implement them.
Copy sent to Sham Chukoury, owner of gitweb-xmms2.
Cleanup, tidying, refactoring:
* HTML code still needs cleanup. All elements should have be either
assigned class, or given unique id. Presentational elements like <i>
or <b> should be replaced by styling using CSS. Page should be divided
into block elements; avoid overuse of <br/>.
* CSS cleanup. Names of classes should reflect intent, not be
replacement for presentational elements, or be incomprehensive:
e.g. classes age0, age1, age2, dark, light. padding: 8px; repeats many
times, perhaps it could be replaced by setting margin in encompassing
element, or via inheritance or additional class.
* Separate generating link and related links to object
(e.g. "blob | blame | history | raw" for blob in "tree" view)
into subroutine, similarly to refactoring navbar. The problem is that
the set of links depends not only on the type of object, but also on
the action/view we are in, for example links to commit object might
be either "commit | commitdiff", or "log | shortlog" if the commit is
considered ref. DISCUSSION needed.
* Collapse similar subroutines into one, e.g. git_blob and
git_blob_plain, and use parameter to set format. Perhaps instead of
having
sub git_commitdiff_plain {
git_commitdiff('plain');
}
we can simply use
my %actions = (
# ...
"commitdiff_plain" => sub { git_commitdiff('plain'); }
# ...
);
Which of this options is more readable, which one is faster?
* Refactoring formatsnav similarly to commit/hashbase related main
navbar (upper part of navbar now). For blob it would be "html",
"plain", "blame", "head" (or "base"), optionally "HEAD", "history",
perhaps later "highlight". For tree it would be "tree", "blame" and
"history". For commit it would be "html", "plain", and "combined"
if applicable.
* Perhaps some of the views should be made into format, e.g. 'shortlog'
and 'log' (and perhaps 'rss') for log views (this includes
"log"/"shortlog" and "history" views), or 'html', 'opml' and
'plain'/'index' for "project_list". DISCUSSION encouraged.
* Things like description or cloneurls (repourls) and further category
should be perhaps available to set in repository config, not only from
additional files in repository.
Gitweb speed:
* Ensure that gitweb is compatibile with mod_perl not only in
Apache::Registry/ModPerl::Registry CGI script compatibility mode,
but also as native mod_perl handler/script. Make it easy to use
FastCGI instead of CGI (perhaps via CGI::Fast).
This could be ensured by creating 'handler'/'main' method which
does parameter reading, validation and dispatching action. Perhaps
we should add gitweb_params subroutine, which given the names
of parameters returns values of needed parameters (either as list of
parameter names and returning list of parameters in order set by
subroutine argument, or as hash with keys and undefined values and
returning hash or hashref with values filled). The exception being
project and action parameters, which must be accessed before
dispatching action.
We could make script options parameters my() again, and leave our()
only for global variables which changes from invocation to invocation,
like $project, $action, $git_dir etc.
* Add new CORE GIT command, git-show-refs, which returns for given
by glob set of refs required fields (specified by --format option),
sorted by given field (specified by --sort option). This would speed
up "tags" and "summary" views considerably.
See Junio post in "[PATCH/RFC] gitweb: Great subroutines renaming"
thread for proposed git-show-refs options.
http://permalink.gmane.org/gmane.comp.version-control.git/25055
Message-Id: <7vejvsyum8.fsf@assigned-by-dhcp.cox.net>
* Try to avoid unnecessary calls to git commands, try do do things
using one command. For example instead of getting list of revisions
from git-rev-list, then parsing commit after commit use one
git-rev-list invocation to get and parse list of revisions.
It would be easier if some CORE GIT commands, for example git-ls-tree,
acquired --stdin option, similarly to git-diff-tree (and output
revision before output for that revison, like git-diff-tree).
* In the future, use Git.pm
Improvements of existing views and features:
* Make pickaxe search a feature (as it is expensive), and document
existing search operators. Perhaps refactor git_search as well.
* Make history follow renames. This could I think be done without CORE
GIT support, but it would be better with it. The proposition is to add
--follow option to git-rev-list (or -C, -M, -B options), which would
make if follow renames in files in path limit; I think following
renames with pathspec being glob is out, unless we expand glob to
individual file names and then follow those, and that following
directory renames would be very hard if not impossible.
Additionally make git-rev-list output current path limit, in format
suitable as argument for other git commands like git-diff-tree, i.e.
<hash> -- <path limit>
instead of current
<hash>
Make git-diff-tree at least accept and understand this kind of input
also on stdin with --stdin option.
* Perhaps add number of changed lines to the short information about
blob (perhaps via title to patch/diff link?), and diffstat to
"commitdiff_plain" view.
* Parse $GIT_DIR/remotes/ to mark tracking branches in "heads" view,
e.g. as a popup.
New features:
* Categories support (from gitweb-xmms2), although I'm not sure about
adding yet another file "category" to git repository. Perhaps first
part of dirname could serve as category name, or we could use
gitweb.category configuration variable.
* Code highlighting in blob view (from gitweb-xmms2), or to generalize
to allow for generalized filter. The higlighter should have support
for HTML support, it should always close elements before end of line,
it would be better if it used CSS for styling, and it should accept
file to highlight on standard input. gitweb-xmms2 uses Highlight
http://www.andre-simon.de/
but GNU Highlight (src-hilite) could be used instead
http://www.gnu.org/software/src-highlite/
* Committags support, i.e. extend hyperlinking commit sha1 to commit
view to hyperlinking bug #nn/BUG(nn) to the proper bugtracker, in both
commit message view and (harder to do properly) in commit
title/subject line which is hyperlink itself. The problem is how to do
this general enough...
I have thought about structure somewhat similar to %feature hash, i.e.
something like %commitfilter hash, with 'enabled', 'override', 'name',
'options' or something like that and of course 'sub' (as we probably
would use $cgi->a(...) to construct hyperlink, and not simple regexp
replacement.
DISCUSSION needed.
* Etags/Ctags/LXR based anchors in the blob view. In gitweb-xmms2 they
use temporary file to avoid race condition for both etags and
highlighting. Is it worth doing? GNU Highlight has ctags
(encumberant-ctags) support built in, I don't know about Highlight.
New views:
* Reflog support: show history of branch. I'm not sure if it is worth
doing, as of now reflogs are local matter, and doesn't get copied on
push even to bare repository.
* ViewVC-like "tree_blame" view. It probably would need CORE GIT support
to have acceptable speed, although version using git-ls-tree wasn't
that slow. Or at least git-ls-tree with --stdin support.
* gitk-ish (qgit-ish) view, with graph showing branches forking and
merging. Not that easy, but probably possible.
In the future:
* AJAX-ize parts of gitweb.
Comments? Other ideas? <wishful thinking>Code?</wishful thinking>
--
Jakub Narebski
ShadeHawk on #git
Poland
--
VGER BF report: H 0
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox