* [PATCH 3/5] Allow alternate "low-level" emit function from xdl_diff
From: René Scharfe @ 2008-10-25 13:30 UTC (permalink / raw)
To: Brian Downing; +Cc: Junio C Hamano, git
In-Reply-To: <48BF0FBF.3010104@lsrfire.ath.cx>
From: Brian Downing <bdowning@lavos.net>
For some users (e.g. git blame), getting textual patch output is just
extra work, as they can get all the information they need from the low-
level diff structures. Allow for an alternate low-level emit function
to be defined to allow bypassing the textual patch generation; set
xemitconf_t's emit_func member to enable this.
The (void (*)()) type is pretty ugly, but the alternative would be to
include most of the private xdiff headers in xdiff.h to get the types
required for the "proper" function prototype. Also, a (void *) won't
work, as ANSI C doesn't allow a function pointer to be cast to an
object pointer.
Signed-off-by: Brian Downing <bdowning@lavos.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
---
Taken from pu.
xdiff/xdiff.h | 1 +
xdiff/xdiffi.c | 4 +++-
xdiff/xemit.c | 3 +--
xdiff/xemit.h | 3 +++
4 files changed, 8 insertions(+), 3 deletions(-)
diff --git a/xdiff/xdiff.h b/xdiff/xdiff.h
index deebe02..84fff58 100644
--- a/xdiff/xdiff.h
+++ b/xdiff/xdiff.h
@@ -87,6 +87,7 @@ typedef struct s_xdemitconf {
unsigned long flags;
find_func_t find_func;
void *find_func_priv;
+ void (*emit_func)();
} xdemitconf_t;
typedef struct s_bdiffparam {
diff --git a/xdiff/xdiffi.c b/xdiff/xdiffi.c
index 1bad846..9d0324a 100644
--- a/xdiff/xdiffi.c
+++ b/xdiff/xdiffi.c
@@ -538,6 +538,8 @@ int xdl_diff(mmfile_t *mf1, mmfile_t *mf2, xpparam_t const *xpp,
xdemitconf_t const *xecfg, xdemitcb_t *ecb) {
xdchange_t *xscr;
xdfenv_t xe;
+ emit_func_t ef = xecfg->emit_func ?
+ (emit_func_t)xecfg->emit_func : xdl_emit_diff;
if (xdl_do_diff(mf1, mf2, xpp, &xe) < 0) {
@@ -551,7 +553,7 @@ int xdl_diff(mmfile_t *mf1, mmfile_t *mf2, xpparam_t const *xpp,
return -1;
}
if (xscr) {
- if (xdl_emit_diff(&xe, xscr, ecb, xecfg) < 0) {
+ if (ef(&xe, xscr, ecb, xecfg) < 0) {
xdl_free_script(xscr);
xdl_free_env(&xe);
diff --git a/xdiff/xemit.c b/xdiff/xemit.c
index d3d9c84..4625c1b 100644
--- a/xdiff/xemit.c
+++ b/xdiff/xemit.c
@@ -27,7 +27,6 @@
static long xdl_get_rec(xdfile_t *xdf, long ri, char const **rec);
static int xdl_emit_record(xdfile_t *xdf, long ri, char const *pre, xdemitcb_t *ecb);
-static xdchange_t *xdl_get_hunk(xdchange_t *xscr, xdemitconf_t const *xecfg);
@@ -58,7 +57,7 @@ static int xdl_emit_record(xdfile_t *xdf, long ri, char const *pre, xdemitcb_t *
* Starting at the passed change atom, find the latest change atom to be included
* inside the differential hunk according to the specified configuration.
*/
-static xdchange_t *xdl_get_hunk(xdchange_t *xscr, xdemitconf_t const *xecfg) {
+xdchange_t *xdl_get_hunk(xdchange_t *xscr, xdemitconf_t const *xecfg) {
xdchange_t *xch, *xchp;
for (xchp = xscr, xch = xscr->next; xch; xchp = xch, xch = xch->next)
diff --git a/xdiff/xemit.h b/xdiff/xemit.h
index 440a739..c2e2e83 100644
--- a/xdiff/xemit.h
+++ b/xdiff/xemit.h
@@ -24,7 +24,10 @@
#define XEMIT_H
+typedef int (*emit_func_t)(xdfenv_t *xe, xdchange_t *xscr, xdemitcb_t *ecb,
+ xdemitconf_t const *xecfg);
+xdchange_t *xdl_get_hunk(xdchange_t *xscr, xdemitconf_t const *xecfg);
int xdl_emit_diff(xdfenv_t *xe, xdchange_t *xscr, xdemitcb_t *ecb,
xdemitconf_t const *xecfg);
--
1.6.0.3.514.g2f91b
^ permalink raw reply related
* [PATCH 4/5] add xdi_diff_hunks() for callers that only need hunk lengths
From: René Scharfe @ 2008-10-25 13:31 UTC (permalink / raw)
To: Brian Downing; +Cc: Junio C Hamano, git
In-Reply-To: <48BF0FBF.3010104@lsrfire.ath.cx>
Based on a patch by Brian Downing, this uses the xdiff emit_func feature
to implement xdi_diff_hunks(). It's a function that calls a callback for
each hunk of a diff, passing its lengths.
Signed-off-by: Rene Scharfe <rene.scharfe@lsrfire.ath.cx>
---
xdiff-interface.c | 49 ++++++++++++++++++++++++++++++++++++++++++++++++-
xdiff-interface.h | 4 ++++
2 files changed, 52 insertions(+), 1 deletions(-)
diff --git a/xdiff-interface.c b/xdiff-interface.c
index 49e06af..e8ef46d 100644
--- a/xdiff-interface.c
+++ b/xdiff-interface.c
@@ -1,6 +1,9 @@
#include "cache.h"
#include "xdiff-interface.h"
-#include "strbuf.h"
+#include "xdiff/xtypes.h"
+#include "xdiff/xdiffi.h"
+#include "xdiff/xemit.h"
+#include "xdiff/xmacros.h"
struct xdiff_emit_state {
xdiff_emit_consume_fn consume;
@@ -153,6 +156,50 @@ int xdi_diff_outf(mmfile_t *mf1, mmfile_t *mf2,
return ret;
}
+struct xdiff_emit_hunk_state {
+ xdiff_emit_hunk_consume_fn consume;
+ void *consume_callback_data;
+};
+
+static int process_diff(xdfenv_t *xe, xdchange_t *xscr, xdemitcb_t *ecb,
+ xdemitconf_t const *xecfg)
+{
+ long s1, s2, same, p_next, t_next;
+ xdchange_t *xch, *xche;
+ struct xdiff_emit_hunk_state *state = ecb->priv;
+ xdiff_emit_hunk_consume_fn fn = state->consume;
+ void *consume_callback_data = state->consume_callback_data;
+
+ for (xch = xscr; xch; xch = xche->next) {
+ xche = xdl_get_hunk(xch, xecfg);
+
+ s1 = XDL_MAX(xch->i1 - xecfg->ctxlen, 0);
+ s2 = XDL_MAX(xch->i2 - xecfg->ctxlen, 0);
+ same = s2 + XDL_MAX(xch->i1 - s1, 0);
+ p_next = xche->i1 + xche->chg1;
+ t_next = xche->i2 + xche->chg2;
+
+ fn(consume_callback_data, same, p_next, t_next);
+ }
+ return 0;
+}
+
+int xdi_diff_hunks(mmfile_t *mf1, mmfile_t *mf2,
+ xdiff_emit_hunk_consume_fn fn, void *consume_callback_data,
+ xpparam_t const *xpp, xdemitconf_t *xecfg)
+{
+ struct xdiff_emit_hunk_state state;
+ xdemitcb_t ecb;
+
+ memset(&state, 0, sizeof(state));
+ memset(&ecb, 0, sizeof(ecb));
+ state.consume = fn;
+ state.consume_callback_data = consume_callback_data;
+ xecfg->emit_func = (void (*)())process_diff;
+ ecb.priv = &state;
+ return xdi_diff(mf1, mf2, xpp, xecfg, &ecb);
+}
+
int read_mmfile(mmfile_t *ptr, const char *filename)
{
struct stat st;
diff --git a/xdiff-interface.h b/xdiff-interface.h
index eaf9cd3..7352b9a 100644
--- a/xdiff-interface.h
+++ b/xdiff-interface.h
@@ -4,12 +4,16 @@
#include "xdiff/xdiff.h"
typedef void (*xdiff_emit_consume_fn)(void *, char *, unsigned long);
+typedef void (*xdiff_emit_hunk_consume_fn)(void *, long, long, long);
int xdi_diff(mmfile_t *mf1, mmfile_t *mf2, xpparam_t const *xpp, xdemitconf_t const *xecfg, xdemitcb_t *ecb);
int xdi_diff_outf(mmfile_t *mf1, mmfile_t *mf2,
xdiff_emit_consume_fn fn, void *consume_callback_data,
xpparam_t const *xpp,
xdemitconf_t const *xecfg, xdemitcb_t *xecb);
+int xdi_diff_hunks(mmfile_t *mf1, mmfile_t *mf2,
+ xdiff_emit_hunk_consume_fn fn, void *consume_callback_data,
+ xpparam_t const *xpp, xdemitconf_t *xecfg);
int parse_hunk_header(char *line, int len,
int *ob, int *on,
int *nb, int *nn);
--
1.6.0.3.514.g2f91b
^ permalink raw reply related
* [PATCH 5/5] blame: use xdi_diff_hunks(), get rid of struct patch
From: René Scharfe @ 2008-10-25 13:31 UTC (permalink / raw)
To: Brian Downing; +Cc: Junio C Hamano, git
In-Reply-To: <48BF0FBF.3010104@lsrfire.ath.cx>
Based on a patch by Brian Downing, this replaces the struct patch based
code for blame passing with calls to xdi_diff_hunks(). This way we
avoid generating and then parsing patches; we only let the interesting
infos be passed to our callbacks instead. This makes blame a bit faster:
$ blame="./git blame -M -C -C -p --incremental v1.6.0"
# master
$ /usr/bin/time $blame Makefile >/dev/null
1.38user 0.14system 0:01.52elapsed 100%CPU (0avgtext+0avgdata 0maxresident)k
0inputs+0outputs (0major+12226minor)pagefaults 0swaps
$ /usr/bin/time $blame cache.h >/dev/null
1.66user 0.13system 0:01.80elapsed 99%CPU (0avgtext+0avgdata 0maxresident)k
0inputs+0outputs (0major+12262minor)pagefaults 0swaps
# this patch series
$ /usr/bin/time $blame Makefile >/dev/null
1.27user 0.12system 0:01.40elapsed 99%CPU (0avgtext+0avgdata 0maxresident)k
0inputs+0outputs (0major+11836minor)pagefaults 0swaps
$ /usr/bin/time $blame cache.h >/dev/null
1.52user 0.12system 0:01.70elapsed 97%CPU (0avgtext+0avgdata 0maxresident)k
0inputs+0outputs (0major+12052minor)pagefaults 0swaps
Signed-off-by: Rene Scharfe <rene.scharfe@lsrfire.ath.cx>
---
Brian, your numbers looked much more impressive. Could you please clock
this code with your repository and the file server.c? I wonder if this
callback mechanism is just too complicated or if your case simply benefits
lots more than the two files from git mentioned above.
The patch series ends here without adding xdiff caching, for two reasons.
It's quite easy to add it; patch 4 from your series applies unchanged and
patch 5 is just needs a few small changes to account for the absence of
compare_buffer(). More importantly, speed actually went down with caching
for the test case. The common tail optimization (xdi_diff() vs. xdl_diff())
seems to beat caching for cache.h and Makefile..
builtin-blame.c | 191 +++++++++++++++----------------------------------------
1 files changed, 52 insertions(+), 139 deletions(-)
diff --git a/builtin-blame.c b/builtin-blame.c
index 5ca7065..b6bc5cf 100644
--- a/builtin-blame.c
+++ b/builtin-blame.c
@@ -443,113 +443,6 @@ static struct origin *find_rename(struct scoreboard *sb,
}
/*
- * Parsing of patch chunks...
- */
-struct chunk {
- /* line number in postimage; up to but not including this
- * line is the same as preimage
- */
- int same;
-
- /* preimage line number after this chunk */
- int p_next;
-
- /* postimage line number after this chunk */
- int t_next;
-};
-
-struct patch {
- struct chunk *chunks;
- int num;
-};
-
-struct blame_diff_state {
- struct patch *ret;
- unsigned hunk_post_context;
- unsigned hunk_in_pre_context : 1;
-};
-
-static void process_u_diff(void *state_, char *line, unsigned long len)
-{
- struct blame_diff_state *state = state_;
- struct chunk *chunk;
- int off1, off2, len1, len2, num;
-
- num = state->ret->num;
- if (len < 4 || line[0] != '@' || line[1] != '@') {
- if (state->hunk_in_pre_context && line[0] == ' ')
- state->ret->chunks[num - 1].same++;
- else {
- state->hunk_in_pre_context = 0;
- if (line[0] == ' ')
- state->hunk_post_context++;
- else
- state->hunk_post_context = 0;
- }
- return;
- }
-
- if (num && state->hunk_post_context) {
- chunk = &state->ret->chunks[num - 1];
- chunk->p_next -= state->hunk_post_context;
- chunk->t_next -= state->hunk_post_context;
- }
- state->ret->num = ++num;
- state->ret->chunks = xrealloc(state->ret->chunks,
- sizeof(struct chunk) * num);
- chunk = &state->ret->chunks[num - 1];
- if (parse_hunk_header(line, len, &off1, &len1, &off2, &len2)) {
- state->ret->num--;
- return;
- }
-
- /* Line numbers in patch output are one based. */
- off1--;
- off2--;
-
- chunk->same = len2 ? off2 : (off2 + 1);
-
- chunk->p_next = off1 + (len1 ? len1 : 1);
- chunk->t_next = chunk->same + len2;
- state->hunk_in_pre_context = 1;
- state->hunk_post_context = 0;
-}
-
-static struct patch *compare_buffer(mmfile_t *file_p, mmfile_t *file_o,
- int context)
-{
- struct blame_diff_state state;
- xpparam_t xpp;
- xdemitconf_t xecfg;
- xdemitcb_t ecb;
-
- memset(&xpp, 0, sizeof(xpp));
- xpp.flags = xdl_opts;
- memset(&xecfg, 0, sizeof(xecfg));
- xecfg.ctxlen = context;
- memset(&state, 0, sizeof(state));
- state.ret = xmalloc(sizeof(struct patch));
- state.ret->chunks = NULL;
- state.ret->num = 0;
-
- xdi_diff_outf(file_p, file_o, process_u_diff, &state, &xpp, &xecfg, &ecb);
-
- if (state.ret->num) {
- struct chunk *chunk;
- chunk = &state.ret->chunks[state.ret->num - 1];
- chunk->p_next -= state.hunk_post_context;
- chunk->t_next -= state.hunk_post_context;
- }
- return state.ret;
-}
-
-static void free_patch(struct patch *p)
-{
- free(p->chunks);
- free(p);
-}
-
-/*
* Link in a new blame entry to the scoreboard. Entries that cover the
* same line range have been removed from the scoreboard previously.
*/
@@ -795,6 +688,22 @@ static void blame_chunk(struct scoreboard *sb,
}
}
+struct blame_chunk_cb_data {
+ struct scoreboard *sb;
+ struct origin *target;
+ struct origin *parent;
+ long plno;
+ long tlno;
+};
+
+static void blame_chunk_cb(void *data, long same, long p_next, long t_next)
+{
+ struct blame_chunk_cb_data *d = data;
+ blame_chunk(d->sb, d->tlno, d->plno, same, d->target, d->parent);
+ d->plno = p_next;
+ d->tlno = t_next;
+}
+
/*
* We are looking at the origin 'target' and aiming to pass blame
* for the lines it is suspected to its parent. Run diff to find
@@ -804,36 +713,28 @@ static int pass_blame_to_parent(struct scoreboard *sb,
struct origin *target,
struct origin *parent)
{
- int i, last_in_target, plno, tlno;
- struct patch *patch;
+ int last_in_target;
mmfile_t file_p, file_o;
+ struct blame_chunk_cb_data d = { sb, target, parent, 0, 0 };
+ xpparam_t xpp;
+ xdemitconf_t xecfg;
last_in_target = find_last_in_target(sb, target);
if (last_in_target < 0)
return 1; /* nothing remains for this target */
- /*
- * Run diff between two origins and grab the patch output, so that
- * we can pass blame for lines origin is currently suspected for
- * to its parent.
- */
fill_origin_blob(parent, &file_p);
fill_origin_blob(target, &file_o);
- patch = compare_buffer(&file_p, &file_o, 0);
num_get_patch++;
- plno = tlno = 0;
- for (i = 0; i < patch->num; i++) {
- struct chunk *chunk = &patch->chunks[i];
-
- blame_chunk(sb, tlno, plno, chunk->same, target, parent);
- plno = chunk->p_next;
- tlno = chunk->t_next;
- }
+ memset(&xpp, 0, sizeof(xpp));
+ xpp.flags = xdl_opts;
+ memset(&xecfg, 0, sizeof(xecfg));
+ xecfg.ctxlen = 0;
+ xdi_diff_hunks(&file_p, &file_o, blame_chunk_cb, &d, &xpp, &xecfg);
/* The rest (i.e. anything after tlno) are the same as the parent */
- blame_chunk(sb, tlno, plno, last_in_target, target, parent);
+ blame_chunk(sb, d.tlno, d.plno, last_in_target, target, parent);
- free_patch(patch);
return 0;
}
@@ -925,6 +826,23 @@ static void handle_split(struct scoreboard *sb,
}
}
+struct handle_split_cb_data {
+ struct scoreboard *sb;
+ struct blame_entry *ent;
+ struct origin *parent;
+ struct blame_entry *split;
+ long plno;
+ long tlno;
+};
+
+static void handle_split_cb(void *data, long same, long p_next, long t_next)
+{
+ struct handle_split_cb_data *d = data;
+ handle_split(d->sb, d->ent, d->tlno, d->plno, same, d->parent, d->split);
+ d->plno = p_next;
+ d->tlno = t_next;
+}
+
/*
* Find the lines from parent that are the same as ent so that
* we can pass blames to it. file_p has the blob contents for
@@ -939,8 +857,9 @@ static void find_copy_in_blob(struct scoreboard *sb,
const char *cp;
int cnt;
mmfile_t file_o;
- struct patch *patch;
- int i, plno, tlno;
+ struct handle_split_cb_data d = { sb, ent, parent, split, 0, 0 };
+ xpparam_t xpp;
+ xdemitconf_t xecfg;
/*
* Prepare mmfile that contains only the lines in ent.
@@ -955,24 +874,18 @@ static void find_copy_in_blob(struct scoreboard *sb,
}
file_o.size = cp - file_o.ptr;
- patch = compare_buffer(file_p, &file_o, 1);
-
/*
* file_o is a part of final image we are annotating.
* file_p partially may match that image.
*/
+ memset(&xpp, 0, sizeof(xpp));
+ xpp.flags = xdl_opts;
+ memset(&xecfg, 0, sizeof(xecfg));
+ xecfg.ctxlen = 1;
memset(split, 0, sizeof(struct blame_entry [3]));
- plno = tlno = 0;
- for (i = 0; i < patch->num; i++) {
- struct chunk *chunk = &patch->chunks[i];
-
- handle_split(sb, ent, tlno, plno, chunk->same, parent, split);
- plno = chunk->p_next;
- tlno = chunk->t_next;
- }
+ xdi_diff_hunks(file_p, &file_o, handle_split_cb, &d, &xpp, &xecfg);
/* remainder, if any, all match the preimage */
- handle_split(sb, ent, tlno, plno, ent->num_lines, parent, split);
- free_patch(patch);
+ handle_split(sb, ent, d.tlno, d.plno, ent->num_lines, parent, split);
}
/*
--
1.6.0.3.514.g2f91b
^ permalink raw reply related
* Re: Performance impact of a large number of commits
From: Samuel Abels @ 2008-10-25 15:12 UTC (permalink / raw)
To: david; +Cc: git
In-Reply-To: <alpine.DEB.1.10.0810242219440.20238@asgard.lang.hm>
On Fri, 2008-10-24 at 22:29 -0700, david@lang.hm wrote:
> when git stores the copies of the files it does a sha1 hash of the file
> contents and then stores the file in the directory
> .git/objects/<first two digits of the hash>/<hash>
> it would be a pretty minor change to git to have it use more directories
Ah, I see how this works. Well, I'll think of a way to cope with this (I
might patch my Git installation, or see how well it performs on an
indexed file system). If all else fails we'll have to slash the number
of commits even if this means that some files are not added to the
history.
> my concern is that spending time creating the pack files will mean that
> you don't have time to insert the new files.
>
> that being said, there may be other ways of dealing with this data rather
> than putting it into files and then adding it to the git repository.
>
> Git has a fast-import streaming format that is designed for programs to
> use that are converting repositories from other SCM systems.
I'm pretty sure that the streaming format won't do us much good, as the
files are re-created from scratch between commits.
Thanks a lot for the information, this was very helpful.
-Samuel
^ permalink raw reply
* [PATCH v2] Fixed git archive for bare repos
From: Deskin Miller @ 2008-10-25 15:38 UTC (permalink / raw)
To: René Scharfe; +Cc: Charles Bailey, git, kenneth johansson, gitster
In-Reply-To: <49024A05.3090100@lsrfire.ath.cx>
From 8f0dce75427283e0333cce1f1e66f4eac9978ad4 Mon Sep 17 00:00:00 2001
From: Charles Bailey <charles@hashpling.org>
This moves the call to git_config to a place where it doesn't break the
logic for using git archive in a bare repository but retains the fix to
make git archive respect core.autocrlf.
Signed-off-by: Charles Bailey <charles@hashpling.org>
Tested-by: Deskin Miller <deskinm@umich.edu>
---
On Sat, Oct 25, 2008 at 12:19:49AM +0200, René Scharfe wrote:
> Charles Bailey schrieb:
> > This moves the call to git config to a place where it doesn't break
> > the logic for using git archive in a bare repository but retains the
> > fix to make git archive respect core.autocrlf.
>
> If one combines your patch, Deskin's commit message and test and extends
> on the latter a bit then I think we have a winner. :)
>
> Here are a few more tests which create a ZIP file in addition to a tar
> archive and compare them to their non-bare counterparts.
>
> Care to resend?
>
> Thanks,
> René
Here's a resend. I've kept Charles's change and commit message, but added
René's tests and removed my test, since it was presupposed by the new tests.
Still needs a signoff from René.
archive.c | 2 ++
builtin-archive.c | 2 --
t/t5000-tar-tree.sh | 21 +++++++++++++++++++++
3 files changed, 23 insertions(+), 2 deletions(-)
diff --git a/archive.c b/archive.c
index e2280df..45d242b 100644
--- a/archive.c
+++ b/archive.c
@@ -338,5 +338,7 @@ int write_archive(int argc, const char **argv, const char *prefix,
parse_treeish_arg(argv, &args, prefix);
parse_pathspec_arg(argv + 1, &args);
+ git_config(git_default_config, NULL);
+
return ar->write_archive(&args);
}
diff --git a/builtin-archive.c b/builtin-archive.c
index 432ce2a..5ceec43 100644
--- a/builtin-archive.c
+++ b/builtin-archive.c
@@ -111,8 +111,6 @@ int cmd_archive(int argc, const char **argv, const char *prefix)
{
const char *remote = NULL;
- git_config(git_default_config, NULL);
-
remote = extract_remote_arg(&argc, argv);
if (remote)
return run_remote_archiver(remote, argc, argv);
diff --git a/t/t5000-tar-tree.sh b/t/t5000-tar-tree.sh
index e395ff4..0f27d73 100755
--- a/t/t5000-tar-tree.sh
+++ b/t/t5000-tar-tree.sh
@@ -58,6 +58,11 @@ test_expect_success \
git commit-tree $treeid </dev/null)'
test_expect_success \
+ 'create bare clone' \
+ 'git clone --bare . bare.git &&
+ cp .gitattributes bare.git/info/attributes'
+
+test_expect_success \
'remove ignored file' \
'rm a/ignored'
@@ -74,6 +79,14 @@ test_expect_success \
'diff b.tar b2.tar'
test_expect_success \
+ 'git archive in a bare repo' \
+ '(cd bare.git && git archive HEAD) >b3.tar'
+
+test_expect_success \
+ 'git archive vs. the same in a bare repo' \
+ 'test_cmp b.tar b3.tar'
+
+test_expect_success \
'validate file modification time' \
'mkdir extract &&
"$TAR" xf b.tar -C extract a/a &&
@@ -151,6 +164,14 @@ test_expect_success \
'git archive --format=zip' \
'git archive --format=zip HEAD >d.zip'
+test_expect_success \
+ 'git archive --format=zip in a bare repo' \
+ '(cd bare.git && git archive --format=zip HEAD) >d1.zip'
+
+test_expect_success \
+ 'git archive --format=zip vs. the same in a bare repo' \
+ 'test_cmp d.zip d1.zip'
+
$UNZIP -v >/dev/null 2>&1
if [ $? -eq 127 ]; then
echo "Skipping ZIP tests, because unzip was not found"
--
1.6.0.3.515.g304f
^ permalink raw reply related
* Re: [PATCH 3/7] gitk: Allow starting gui blame for a specific line.
From: Alexander Gavrilov @ 2008-10-25 16:45 UTC (permalink / raw)
To: Paul Mackerras; +Cc: git
In-Reply-To: <18691.2467.601039.480382@cargo.ozlabs.ibm.com>
On Saturday 25 October 2008 15:57:23 Paul Mackerras wrote:
> > + # Now scan the lines to determine offset within the hunk
> > + set parent {}
> > + set dline 0
> > + set s_lno [lindex [split $s_lix "."] 0]
> > +
> > + for {set i $line} {$i > $s_lno} {incr i -1} {
> > + set c_line [$ctext get $i.0 "$i.0 + 1 lines"]
> > + # Determine if the line is removed
> > + set chunk [string range $c_line 0 [llength $base_lines]-2]
>
> You need an [expr]:
>
> set chunk [string range $c_line 0 [expr {[llength $base_lines] - 2}]]
Ugh. I guess I'll have to install docs from Tcl 8.4...
> > + set removed_idx [string first "-" $chunk]
> > + # Choose a parent index
> > + if {$parent eq {}} {
> > + if {$removed_idx >= 0} {
> > + set parent $removed_idx
> > + incr parent
> > + } else {
> > + set unchanged_idx [string first " " $chunk]
> > + if {$unchanged_idx >= 0} {
> > + set parent $unchanged_idx
> > + incr parent
> > + } else {
> > + # blame the current commit
> > + set parent 0
> > + }
> > + }
> > + }
>
> I like this better than the previous version, but it would turn out a
> bit simpler if you use parent = -1 to indicate that we're blaming the
> current commit, and then increment it right at the end.
Yes, it's probably better to apply the following fixup.
Alexander
diff --git a/gitk b/gitk
index 6fbd6bb..68f07c2 100755
--- a/gitk
+++ b/gitk
@@ -3160,33 +3160,32 @@ proc find_hunk_blamespec {base line} {
# Now scan the lines to determine offset within the hunk
set parent {}
+ set max_parent [expr {[llength $base_lines]-2}]
set dline 0
set s_lno [lindex [split $s_lix "."] 0]
for {set i $line} {$i > $s_lno} {incr i -1} {
set c_line [$ctext get $i.0 "$i.0 + 1 lines"]
# Determine if the line is removed
- set chunk [string range $c_line 0 [llength $base_lines]-2]
+ set chunk [string range $c_line 0 $max_parent]
set removed_idx [string first "-" $chunk]
# Choose a parent index
if {$parent eq {}} {
if {$removed_idx >= 0} {
set parent $removed_idx
- incr parent
} else {
set unchanged_idx [string first " " $chunk]
if {$unchanged_idx >= 0} {
set parent $unchanged_idx
- incr parent
} else {
# blame the current commit
- set parent 0
+ set parent -1
}
}
}
# then count other lines that belong to it
- if {$parent > 0} {
- set code [string index $c_line $parent-1]
+ if {$parent >= 0} {
+ set code [string index $c_line $parent]
if {$code eq "-" || ($removed_idx < 0 && $code ne "+")} {
incr dline
}
@@ -3197,7 +3196,8 @@ proc find_hunk_blamespec {base line} {
}
}
- if {$parent eq {}} { set parent 0 }
+ if {$parent eq {}} { set parent -1 }
+ incr parent
incr dline [lindex $base_lines $parent]
return [list $parent $dline]
}
^ permalink raw reply related
* Re: [PATCH 1/2] Fix git branch -m for symrefs.
From: Junio C Hamano @ 2008-10-25 18:31 UTC (permalink / raw)
To: Miklos Vajna; +Cc: Jeff King, Brandon Casey, git
In-Reply-To: <a96243124c555cbc4081f733b348252ac200bd53.1224939436.git.vmiklos@frugalware.org>
Miklos Vajna <vmiklos@frugalware.org> writes:
> -int delete_ref(const char *refname, const unsigned char *sha1)
> +int delete_ref(const char *refname, const unsigned char *sha1, int flags)
> {
> struct ref_lock *lock;
> - int err, i, ret = 0, flag = 0;
> + int err, i = 0, ret = 0, flag = 0;
> + char *path;
>
> lock = lock_ref_sha1_basic(refname, sha1, 0, &flag);
> if (!lock)
> return 1;
> if (!(flag & REF_ISPACKED)) {
Two variables flag vs flags is a bit confusing, isn't it? How about
naming the new one "delopt" or something?
The new variable "char *path" at the toplevel can be confined in the scope
of this if () {} block and probably can become "const char *", right?
> @@ -964,10 +971,15 @@ int rename_ref(const char *oldref, const char *newref, const char *logmsg)
> struct ref_lock *lock;
> struct stat loginfo;
> int log = !lstat(git_path("logs/%s", oldref), &loginfo);
> + const char *symref = NULL;
> + int is_symref = 0;
>
> if (S_ISLNK(loginfo.st_mode))
> return error("reflog for %s is a symlink", oldref);
Possible bug in the context. When there is no reflog for the ref being
renamed, lstat would fail; it doesn't feel right to have this S_ISLNK()
before checking the result of the lstat which is in "log".
> + symref = resolve_ref(oldref, orig_sha1, 0, &flag);
> + if (flag & REF_ISSYMREF)
> + is_symref = 1;
> if (!resolve_ref(oldref, orig_sha1, 1, &flag))
> return error("refname %s not found", oldref);
Do we really need two calls to resolve_ref()? Your new call calls it
without must-exist bit --- why? Immediately after that, the existing call
will barf if it does not exist anyway.
I agree it is good to have symref aware delete_ref(), but I am not sure
supporting symref in rename_ref() is either needed or necessarily a good
idea. You also need to worry about a symref pointing at a branch yet to
be born.
In the meantime, I think we should just check (flag & REF_ISSYMREF) after
the existing resolve_ref() we can see in the context above, and error out
saying you cannot rename a symref, and do nothing else.
^ permalink raw reply
* Re: [PATCH 4/7] textconv: don't convert for every operation
From: Junio C Hamano @ 2008-10-25 18:32 UTC (permalink / raw)
To: Jeff King; +Cc: Johannes Sixt, Matthieu Moy, git
In-Reply-To: <20081025071912.GA24287@coredump.intra.peff.net>
Jeff King <peff@peff.net> writes:
>> I am also somewhat worried about the performance impact of running
>> get_textconv() to the same filespec many times when no textconv is
>> defined, which is the normal case we should optimize for. It appears that
>> diff_filespec_load_driver() is optimized for a wrong case (i.e. "we
>> already know this needs a custom driver and we know which one").
>
> No, it is the same as before. We always end up with a driver at the end
> of the function, so further calls will be no-ops. So we do exactly one
> attribute lookup per filespec, caching the result.
Ah, I missed that driver named "default". Sorry for the noise.
> I think it makes sense to figure out _what_ needs fixed first, because
> it might be somewhat minor. So far I see:
>
> - leak from fill_mmfile; this definitely needs fixed. The quick fix is
> minor (free if we did a textconv). A more involved fix is to pull it
> out of fill_mmfile entirely and put the code directly into
> builtin_diff, which would be part of a re-roll of this latest
> series. But see below.
>
> - Keep fill_mmfile allocation semantics clear. I was trying to keep
> it simple for other fill_mmfile callers to opt-in to textconv, even
> if they chose to do it by some user-controlled mechanism instead of
> by default (e.g., diff.TextconvDiffstat or something). But maybe
> that is not of value to us. Again, that is a re-roll of this series.
It would be either:
(1) non-textconv users call fill_mmfile(&mf, ..., 0), use mf and return
without clean-up as before, while textconv users do:
fill_mmfile(&mf, ..., 1);
use mf;
if (mf->ptr != one->data)
clean up mf->ptr;
return;
or
(2) non-textconv users are unchanged from v1.6.0, while textconv users
do:
const char *textconv = get_textconv(...);
fill_mmfile(&mf, ...); /* no change to fill_mmfile() */
if (textconv)
munge_mmfile(&mf);
use mf;
if (textconv)
cleanup_mmfile(&mf);
The end result may not be that much different, but I find the latter
easier to follow for three reasons:
* we expect that majority of the users of fill_mmfile() are non textconv
users. I'd feel safer to keep their codepath the same as v1.6.0;
* fill_mmfile() semantics is the same as long before -- it just gives it
a borrowed pointer;
* the code that makes a change to mmfile that requires clean-up does so
explicitly, and that is followed by an explicit clean-up, both
contained in the same function;
> - performance considerations with driver loading. I believe this is a
> non-issue. So either you are reading the code wrong,...
Yes I was. Thanks and sorry.
^ permalink raw reply
* git export to svn
From: Warren Harris @ 2008-10-25 18:40 UTC (permalink / raw)
To: git
Is there a way to export a git repository along with its history to
svn? (git svn init seems to want to go in the other direction.) I know
this is in some sense "going backwards" but I need to commit my work
to a client. Thanks,
Warren
^ permalink raw reply
* Re: git export to svn
From: Warren Harris @ 2008-10-25 19:11 UTC (permalink / raw)
To: J.H.; +Cc: git
In-Reply-To: <1224960205.2874.11.camel@localhost.localdomain>
John,
Thanks for your quick reply. I tried that, but got the following error:
$ git clone ../test2/
Initialized empty Git repository in /Users/warren/projects/tmp/test2-
git-clone/test2/.git/
# ...svn test2 dir already created with subdirs trunk, tags and
branches...
$ git svn init https://svn/svn/SANDBOX/warren/test2 -T trunk -t tags -
b branches
Using higher level of URL: https://svn/svn/SANDBOX/warren/test2 => https://svn/svn
$ git svn dcommit
Can't call method "full_url" on an undefined value at /opt/local/
libexec/git-core/git-svn line 425.
I then tried the hints from here: http://www.basementcoders.com/2008/9/30/git-svn-gotcha
, but still no luck:
$ git merge --no-ff master
Already up-to-date.
$ git svn dcommit
Can't call method "full_url" on an undefined value at /opt/local/
libexec/git-core/git-svn line 425.
Warren
On Oct 25, 2008, at 11:43 AM, J.H. wrote:
> The basic way you would want to do it, it attach your git tree to SVN
> and then git svn dcommit - which will replay the uncommitted changes
> back into SVN - git svn init will do the attachment - assuming that
> your
> git / svn repositories are at least based from the same place.
>
> - John 'Warthog9' Hawley
>
> On Sat, 2008-10-25 at 11:40 -0700, Warren Harris wrote:
>> Is there a way to export a git repository along with its history to
>> svn? (git svn init seems to want to go in the other direction.) I
>> know
>> this is in some sense "going backwards" but I need to commit my work
>> to a client. Thanks,
>>
>> Warren
>> --
>> To unsubscribe from this list: send the line "unsubscribe git" in
>> the body of a message to majordomo@vger.kernel.org
>> More majordomo info at http://vger.kernel.org/majordomo-info.html
>
^ permalink raw reply
* Re: [PATCH v2] Fixed git archive for bare repos
From: Junio C Hamano @ 2008-10-25 19:15 UTC (permalink / raw)
To: Deskin Miller
Cc: René Scharfe, Charles Bailey, git, kenneth johansson,
gitster
In-Reply-To: <20081025153814.GA26752@euler>
Thanks all. Will apply to 'maint' for 1.6.0.4.
^ permalink raw reply
* Re: git export to svn
From: J.H. @ 2008-10-25 18:43 UTC (permalink / raw)
To: Warren Harris; +Cc: git
In-Reply-To: <FC51BBF1-B2CA-4A00-9312-2333FDA537C2@gmail.com>
The basic way you would want to do it, it attach your git tree to SVN
and then git svn dcommit - which will replay the uncommitted changes
back into SVN - git svn init will do the attachment - assuming that your
git / svn repositories are at least based from the same place.
- John 'Warthog9' Hawley
On Sat, 2008-10-25 at 11:40 -0700, Warren Harris wrote:
> Is there a way to export a git repository along with its history to
> svn? (git svn init seems to want to go in the other direction.) I know
> this is in some sense "going backwards" but I need to commit my work
> to a client. Thanks,
>
> Warren
> --
> To unsubscribe from this list: send the line "unsubscribe git" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* Re: [PATCH 4/7] textconv: don't convert for every operation
From: Jeff King @ 2008-10-25 19:35 UTC (permalink / raw)
To: Junio C Hamano; +Cc: Johannes Sixt, Matthieu Moy, git
In-Reply-To: <7v3aika5l7.fsf@gitster.siamese.dyndns.org>
On Sat, Oct 25, 2008 at 11:32:20AM -0700, Junio C Hamano wrote:
> The end result may not be that much different, but I find the latter
> easier to follow for three reasons:
Your reasoning here is sound. My initial thought was to make it a
one-liner change to "turn on" text conversion in other spots. But
a) it didn't turn out that way, since you still have to keep track of
the "did I textconv" when determining binary-ness, and whether to
free()
b) we don't actually want to do it anywhere else (except perhaps, as I
mentioned, in blame, but that is a totally different interface
anyway)
I will re-roll my latest series according to your recommendation
(unless you are set on reverting the first part; if so, please tell me
asap so I can work under that assumption).
-Peff
^ permalink raw reply
* Re: [PATCH 5/5] blame: use xdi_diff_hunks(), get rid of struct patch
From: Junio C Hamano @ 2008-10-25 19:36 UTC (permalink / raw)
To: René Scharfe; +Cc: Brian Downing, git
In-Reply-To: <49031FB8.8060003@lsrfire.ath.cx>
René Scharfe <rene.scharfe@lsrfire.ath.cx> writes:
> Based on a patch by Brian Downing, this replaces the struct patch based
> code for blame passing with calls to xdi_diff_hunks(). This way we
> avoid generating and then parsing patches; we only let the interesting
> infos be passed to our callbacks instead. This makes blame a bit faster:
>
> $ blame="./git blame -M -C -C -p --incremental v1.6.0"
>
> # master
> $ /usr/bin/time $blame Makefile >/dev/null
> 1.38user 0.14system 0:01.52elapsed 100%CPU (0avgtext+0avgdata 0maxresident)k
> 0inputs+0outputs (0major+12226minor)pagefaults 0swaps
> $ /usr/bin/time $blame cache.h >/dev/null
> 1.66user 0.13system 0:01.80elapsed 99%CPU (0avgtext+0avgdata 0maxresident)k
> 0inputs+0outputs (0major+12262minor)pagefaults 0swaps
>
> # this patch series
> $ /usr/bin/time $blame Makefile >/dev/null
> 1.27user 0.12system 0:01.40elapsed 99%CPU (0avgtext+0avgdata 0maxresident)k
> 0inputs+0outputs (0major+11836minor)pagefaults 0swaps
> $ /usr/bin/time $blame cache.h >/dev/null
> 1.52user 0.12system 0:01.70elapsed 97%CPU (0avgtext+0avgdata 0maxresident)k
> 0inputs+0outputs (0major+12052minor)pagefaults 0swaps
>
> Signed-off-by: Rene Scharfe <rene.scharfe@lsrfire.ath.cx>
The resulting series reads quite clean. I like it.
> Brian, your numbers looked much more impressive. Could you please clock
> this code with your repository and the file server.c? I wonder if this
> callback mechanism is just too complicated or if your case simply benefits
> lots more than the two files from git mentioned above.
>
> The patch series ends here without adding xdiff caching, for two reasons.
> It's quite easy to add it; patch 4 from your series applies unchanged and
> patch 5 is just needs a few small changes to account for the absence of
> compare_buffer(). More importantly, speed actually went down with caching
> for the test case. The common tail optimization (xdi_diff() vs. xdl_diff())
> seems to beat caching for cache.h and Makefile..
Perhaps revision.c in our history would be more interesting than cache.h
or Makefile, as there are more line migrations from different places to
that file.
^ permalink raw reply
* Re: git export to svn
From: J.H. @ 2008-10-25 20:12 UTC (permalink / raw)
To: Warren Harris; +Cc: git
In-Reply-To: <77DFC428-35AE-4F66-9D9F-3D4E0005727D@gmail.com>
Even with init - your going to need to do a fetch so that you have a
copy of the svn in your tree - if the git tree you've already got has
the svn references (take a look at git-log if it seems to have an svn
line in the log then at some point someone pulled in the svn tree into
git) if not your going to effectively be pulling the entire svn tree
into your git tree.
The only other real way to get your changes / patches into svn is to
dump them out as patches and them individually apply / commit them to
your svn tree.
- John 'Warthog9' Hawley
On Sat, 2008-10-25 at 12:11 -0700, Warren Harris wrote:
> John,
>
> Thanks for your quick reply. I tried that, but got the following error:
>
>
> $ git clone ../test2/
> Initialized empty Git repository in /Users/warren/projects/tmp/test2-
> git-clone/test2/.git/
> # ...svn test2 dir already created with subdirs trunk, tags and
> branches...
> $ git svn init https://svn/svn/SANDBOX/warren/test2 -T trunk -t tags -
> b branches
> Using higher level of URL: https://svn/svn/SANDBOX/warren/test2 => https://svn/svn
> $ git svn dcommit
> Can't call method "full_url" on an undefined value at /opt/local/
> libexec/git-core/git-svn line 425.
>
> I then tried the hints from here: http://www.basementcoders.com/2008/9/30/git-svn-gotcha
> , but still no luck:
>
> $ git merge --no-ff master
> Already up-to-date.
> $ git svn dcommit
> Can't call method "full_url" on an undefined value at /opt/local/
> libexec/git-core/git-svn line 425.
>
>
> Warren
>
>
> On Oct 25, 2008, at 11:43 AM, J.H. wrote:
>
> > The basic way you would want to do it, it attach your git tree to SVN
> > and then git svn dcommit - which will replay the uncommitted changes
> > back into SVN - git svn init will do the attachment - assuming that
> > your
> > git / svn repositories are at least based from the same place.
> >
> > - John 'Warthog9' Hawley
> >
> > On Sat, 2008-10-25 at 11:40 -0700, Warren Harris wrote:
> >> Is there a way to export a git repository along with its history to
> >> svn? (git svn init seems to want to go in the other direction.) I
> >> know
> >> this is in some sense "going backwards" but I need to commit my work
> >> to a client. Thanks,
> >>
> >> Warren
> >> --
> >> To unsubscribe from this list: send the line "unsubscribe git" in
> >> the body of a message to majordomo@vger.kernel.org
> >> More majordomo info at http://vger.kernel.org/majordomo-info.html
> >
>
> --
> To unsubscribe from this list: send the line "unsubscribe git" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* Re: Problem with git filter-branch
From: Johannes Schindelin @ 2008-10-25 20:36 UTC (permalink / raw)
To: Pascal Obry; +Cc: git list
In-Reply-To: <4902E7D8.6050401@obry.net>
Hi,
On Sat, 25 Oct 2008, Pascal Obry wrote:
> Anyway, I used to run the following command:
>
> $ git filter-branch --tag-name-filter cat --parent-filter "sed -e
> 's/^$/-p c96d4da294667de1800687d25340551683153002/'" svn-release_2_6
>
> without problem, I now get this:
>
> Namespace refs/original/ not empty
> rm: cannot remove directory
> `/home/obry/dev/repositories/git/proj/.git-rewrite': Directory not empty
It is a (maybe ill-conceived) feature. When branches are rewritten, their
original versions are stored in the refs/original/ namespace. You can
force overwriting with "-f".
I wonder if people would like to have this feature removed; reflogs should
be enough.
Thoughts?
Ciao,
Dscho
^ permalink raw reply
* Re: git export to svn
From: Warren Harris @ 2008-10-25 20:29 UTC (permalink / raw)
To: J.H.; +Cc: git
In-Reply-To: <1224965564.2874.49.camel@localhost.localdomain>
I tried a fetch, but still no luck:
$ git svn fetch
W: Ignoring error from SVN, path probably does not exist: (175002): RA
layer request failed: REPORT of '/svn/!svn/bc/100': Could not read
chunk size: Secure connection truncated (https://svn)
W: Do not be alarmed at the above message git-svn is just searching
aggressively for old history.
This may take a while on large repositories
r58084 = c01dadf89b552077da132273485e7569d8694518 (trunk)
A ...
r58088 = 7916f3a02ad6c759985bd9fb886423c373a72125 (trunk)
$ git svn rebase
Unable to determine upstream SVN information from working tree history
$ git svn dcommit
Can't call method "full_url" on an undefined value at /opt/local/
libexec/git-core/git-svn line 425.
Looks like the only option is applying individual patches to preserve
my history...
Warren
On Oct 25, 2008, at 1:12 PM, J.H. wrote:
> Even with init - your going to need to do a fetch so that you have a
> copy of the svn in your tree - if the git tree you've already got has
> the svn references (take a look at git-log if it seems to have an svn
> line in the log then at some point someone pulled in the svn tree into
> git) if not your going to effectively be pulling the entire svn tree
> into your git tree.
>
> The only other real way to get your changes / patches into svn is to
> dump them out as patches and them individually apply / commit them to
> your svn tree.
>
> - John 'Warthog9' Hawley
>
>
> On Sat, 2008-10-25 at 12:11 -0700, Warren Harris wrote:
>> John,
>>
>> Thanks for your quick reply. I tried that, but got the following
>> error:
>>
>>
>> $ git clone ../test2/
>> Initialized empty Git repository in /Users/warren/projects/tmp/test2-
>> git-clone/test2/.git/
>> # ...svn test2 dir already created with subdirs trunk, tags and
>> branches...
>> $ git svn init https://svn/svn/SANDBOX/warren/test2 -T trunk -t
>> tags -
>> b branches
>> Using higher level of URL: https://svn/svn/SANDBOX/warren/test2 => https://svn/svn
>> $ git svn dcommit
>> Can't call method "full_url" on an undefined value at /opt/local/
>> libexec/git-core/git-svn line 425.
>>
>> I then tried the hints from here: http://www.basementcoders.com/2008/9/30/git-svn-gotcha
>> , but still no luck:
>>
>> $ git merge --no-ff master
>> Already up-to-date.
>> $ git svn dcommit
>> Can't call method "full_url" on an undefined value at /opt/local/
>> libexec/git-core/git-svn line 425.
>>
>>
>> Warren
>>
>>
>> On Oct 25, 2008, at 11:43 AM, J.H. wrote:
>>
>>> The basic way you would want to do it, it attach your git tree to
>>> SVN
>>> and then git svn dcommit - which will replay the uncommitted changes
>>> back into SVN - git svn init will do the attachment - assuming that
>>> your
>>> git / svn repositories are at least based from the same place.
>>>
>>> - John 'Warthog9' Hawley
>>>
>>> On Sat, 2008-10-25 at 11:40 -0700, Warren Harris wrote:
>>>> Is there a way to export a git repository along with its history to
>>>> svn? (git svn init seems to want to go in the other direction.) I
>>>> know
>>>> this is in some sense "going backwards" but I need to commit my
>>>> work
>>>> to a client. Thanks,
>>>>
>>>> Warren
>>>> --
>>>> To unsubscribe from this list: send the line "unsubscribe git" in
>>>> the body of a message to majordomo@vger.kernel.org
>>>> More majordomo info at http://vger.kernel.org/majordomo-info.html
>>>
>>
>> --
>> To unsubscribe from this list: send the line "unsubscribe git" in
>> the body of a message to majordomo@vger.kernel.org
>> More majordomo info at http://vger.kernel.org/majordomo-info.html
>
^ permalink raw reply
* Re: Problem with git filter-branch
From: Mike Hommey @ 2008-10-25 20:40 UTC (permalink / raw)
To: Johannes Schindelin; +Cc: Pascal Obry, git list
In-Reply-To: <alpine.DEB.1.00.0810252235040.22125@pacific.mpi-cbg.de.mpi-cbg.de>
On Sat, Oct 25, 2008 at 10:36:26PM +0200, Johannes Schindelin wrote:
> Hi,
>
> On Sat, 25 Oct 2008, Pascal Obry wrote:
>
> > Anyway, I used to run the following command:
> >
> > $ git filter-branch --tag-name-filter cat --parent-filter "sed -e
> > 's/^$/-p c96d4da294667de1800687d25340551683153002/'" svn-release_2_6
> >
> > without problem, I now get this:
> >
> > Namespace refs/original/ not empty
> > rm: cannot remove directory
> > `/home/obry/dev/repositories/git/proj/.git-rewrite': Directory not empty
>
> It is a (maybe ill-conceived) feature. When branches are rewritten, their
> original versions are stored in the refs/original/ namespace. You can
> force overwriting with "-f".
>
> I wonder if people would like to have this feature removed; reflogs should
> be enough.
I have never have had use for the refs/original namespace, and I used
filter-branch more than a couple of times. Though I would certainly
understand that people would not be confident enough not to have a
parachute. Reflog would indeed be enough, as long as it is not
branch@{42000} that needs to be used. Haven't checked, but theorically,
it should be branch@{1} in all cases, so no problem here.
Mike
^ permalink raw reply
* Re: Problem with git filter-branch
From: Pascal Obry @ 2008-10-25 20:55 UTC (permalink / raw)
To: Johannes Schindelin; +Cc: git list
In-Reply-To: <alpine.DEB.1.00.0810252235040.22125@pacific.mpi-cbg.de.mpi-cbg.de>
Hi Johannes,
> It is a (maybe ill-conceived) feature. When branches are rewritten, their
> original versions are stored in the refs/original/ namespace. You can
> force overwriting with "-f".
Working fine indeed with -f option. What's strange is that it used to
work without the -f option. Would be nice to improve the error message
in this specific case.
Anyway, thanks a lot.
--
--|------------------------------------------------------
--| Pascal Obry Team-Ada Member
--| 45, rue Gabriel Peri - 78114 Magny Les Hameaux FRANCE
--|------------------------------------------------------
--| http://www.obry.net
--| "The best way to travel is by means of imagination"
--|
--| gpg --keyserver wwwkeys.pgp.net --recv-key C1082595
^ permalink raw reply
* [PATCH] git-gui: Update German translation.
From: Christian Stimming @ 2008-10-25 20:55 UTC (permalink / raw)
To: Shawn Pearce; +Cc: git
[-- Attachment #1: Type: text/plain, Size: 875 bytes --]
Attached to avoid whitespace problems.
By the way, the newly added menu entry "Remote"->"Remove Remote" is highly
user-unfriendly, as it isn't obvious here what the menu item will do and the
cost of erroneously selecting this is rather high. Obviously this is the
counterpart to "Remote"->"Add...", which, as the menu promises, will give me
the opportunity to confirm what I'm going to do next. In contrast to
this, "Remote"->"Remove Remote" doesn't ask for any confirmation, but will
directly remove the link to the remote from my working copy. As a
non-git-guru, restoring this link to the remote is a non-trivial task. In the
sense of GUI symmetry and meeting user expectations, "Remove" as a
counterpart to "Add" should be a menu item like "Remove..." which also waits
for confirmation before removing the remote. Or did I miss something?
Regards,
Christian
[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: 0001-git-gui-Update-German-translation.patch --]
[-- Type: text/x-diff; charset="us-ascii"; name="0001-git-gui-Update-German-translation.patch", Size: 12130 bytes --]
From 2e80b2096cc662e7694b0ac774df169747831d33 Mon Sep 17 00:00:00 2001
From: Christian Stimming <stimming@tuhh.de>
Date: Sat, 25 Oct 2008 22:51:05 +0200
Subject: [PATCH] git-gui: Update German translation.
Not yet completed, though.
Signed-off-by: Christian Stimming <stimming@tuhh.de>
---
po/de.po | 279 +++++++++++++++++++++++++++++++++++++++++++++++++++----------
1 files changed, 233 insertions(+), 46 deletions(-)
diff --git a/po/de.po b/po/de.po
index 793cca1..5c04812 100644
--- a/po/de.po
+++ b/po/de.po
@@ -7,8 +7,8 @@ msgid ""
msgstr ""
"Project-Id-Version: git-gui\n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2008-09-13 10:20+0200\n"
-"PO-Revision-Date: 2008-09-13 10:24+0200\n"
+"POT-Creation-Date: 2008-10-25 13:32+0200\n"
+"PO-Revision-Date: 2008-10-25 22:47+0200\n"
"Last-Translator: Christian Stimming <stimming@tuhh.de>\n"
"Language-Team: German\n"
"MIME-Version: 1.0\n"
@@ -86,7 +86,17 @@ msgstr "Dateistatus aktualisieren..."
msgid "Scanning for modified files ..."
msgstr "Nach geänderten Dateien suchen..."
-#: git-gui.sh:1324 lib/browser.tcl:246
+#: git-gui.sh:1325
+#, fuzzy
+msgid "Calling prepare-commit-msg hook..."
+msgstr "Aufrufen der Vor-Eintragen-Kontrolle..."
+
+#: git-gui.sh:1342
+#, fuzzy
+msgid "Commit declined by prepare-commit-msg hook."
+msgstr "Eintragen abgelehnt durch Vor-Eintragen-Kontrolle (»pre-commit hook«)."
+
+#: git-gui.sh:1502 lib/browser.tcl:246
msgid "Ready."
msgstr "Bereit."
@@ -170,7 +180,11 @@ msgstr "Zusammenführen"
msgid "Remote"
msgstr "Andere Archive"
-#: git-gui.sh:1879
+#: git-gui.sh:2242
+msgid "Explore Working Copy"
+msgstr "Arbeitskopie im Dateimanager"
+
+#: git-gui.sh:2247
msgid "Browse Current Branch's Files"
msgstr "Aktuellen Zweig durchblättern"
@@ -267,7 +281,15 @@ msgstr "Löschen..."
msgid "Reset..."
msgstr "Zurücksetzen..."
-#: git-gui.sh:2002 git-gui.sh:2389
+#: git-gui.sh:2372
+msgid "Done"
+msgstr "Fertig"
+
+#: git-gui.sh:2374
+msgid "Commit@@verb"
+msgstr "Eintragen"
+
+#: git-gui.sh:2383 git-gui.sh:2786
msgid "New Commit"
msgstr "Neue Version"
@@ -307,11 +329,7 @@ msgstr "Mehr Zeilen anzeigen"
msgid "Sign Off"
msgstr "Abzeichnen"
-#: git-gui.sh:2053 git-gui.sh:2372
-msgid "Commit@@verb"
-msgstr "Eintragen"
-
-#: git-gui.sh:2064
+#: git-gui.sh:2458
msgid "Local Merge..."
msgstr "Lokales Zusammenführen..."
@@ -319,11 +337,19 @@ msgstr "Lokales Zusammenführen..."
msgid "Abort Merge..."
msgstr "Zusammenführen abbrechen..."
-#: git-gui.sh:2081
+#: git-gui.sh:2475
+msgid "Add..."
+msgstr "Hinzufügen..."
+
+#: git-gui.sh:2479
msgid "Push..."
msgstr "Versenden..."
-#: git-gui.sh:2197 git-gui.sh:2219 lib/about.tcl:14
+#: git-gui.sh:2483
+msgid "Delete Branch..."
+msgstr "Zweig löschen..."
+
+#: git-gui.sh:2493 git-gui.sh:2515 lib/about.tcl:14
#: lib/choose_repository.tcl:44 lib/choose_repository.tcl:50
#, tcl-format
msgid "About %s"
@@ -416,7 +442,11 @@ msgstr "Schriftgröße verkleinern"
msgid "Increase Font Size"
msgstr "Schriftgröße vergrößern"
-#: git-gui.sh:2870
+#: git-gui.sh:3033 lib/blame.tcl:281
+msgid "Encoding"
+msgstr "Zeichenkodierung"
+
+#: git-gui.sh:3044
msgid "Apply/Reverse Hunk"
msgstr "Kontext anwenden/umkehren"
@@ -440,11 +470,7 @@ msgstr "Lokale Version benutzen"
msgid "Revert To Base"
msgstr "Ursprüngliche Version benutzen"
-#: git-gui.sh:2906
-msgid "Stage Working Copy"
-msgstr "Arbeitskopie bereitstellen"
-
-#: git-gui.sh:2925
+#: git-gui.sh:3091
msgid "Unstage Hunk From Commit"
msgstr "Kontext aus Bereitstellung herausnehmen"
@@ -583,7 +609,12 @@ msgstr "Eintragender:"
msgid "Original File:"
msgstr "Ursprüngliche Datei:"
-#: lib/blame.tcl:990
+#: lib/blame.tcl:1013
+#, fuzzy
+msgid "Cannot find HEAD commit:"
+msgstr "Elternversion kann nicht gefunden werden:"
+
+#: lib/blame.tcl:1068
msgid "Cannot find parent commit:"
msgstr "Elternversion kann nicht gefunden werden:"
@@ -1041,11 +1072,15 @@ msgstr "Datei »%s« existiert bereits."
msgid "Clone"
msgstr "Klonen"
-#: lib/choose_repository.tcl:468
-msgid "URL:"
-msgstr "URL:"
+#: lib/choose_repository.tcl:467
+msgid "Source Location:"
+msgstr ""
+
+#: lib/choose_repository.tcl:478
+msgid "Target Directory:"
+msgstr "Zielverzeichnis:"
-#: lib/choose_repository.tcl:489
+#: lib/choose_repository.tcl:490
msgid "Clone Type:"
msgstr "Art des Klonens:"
@@ -1525,7 +1560,27 @@ msgstr ""
msgid "Loading diff of %s..."
msgstr "Vergleich von »%s« laden..."
-#: lib/diff.tcl:114 lib/diff.tcl:184
+#: lib/diff.tcl:120
+msgid ""
+"LOCAL: deleted\n"
+"REMOTE:\n"
+msgstr ""
+
+#: lib/diff.tcl:125
+msgid ""
+"REMOTE: deleted\n"
+"LOCAL:\n"
+msgstr ""
+
+#: lib/diff.tcl:132
+msgid "LOCAL:\n"
+msgstr ""
+
+#: lib/diff.tcl:135
+msgid "REMOTE:\n"
+msgstr ""
+
+#: lib/diff.tcl:197 lib/diff.tcl:296
#, tcl-format
msgid "Unable to display %s"
msgstr "Datei »%s« kann nicht angezeigt werden"
@@ -1542,7 +1597,22 @@ msgstr "Git-Projektarchiv (Unterprojekt)"
msgid "* Binary file (not showing content)."
msgstr "* Binärdatei (Inhalt wird nicht angezeigt)"
-#: lib/diff.tcl:313
+#: lib/diff.tcl:222
+#, tcl-format
+msgid ""
+"* Untracked file is %d bytes.\n"
+"* Showing only first %d bytes.\n"
+msgstr ""
+
+#: lib/diff.tcl:228
+#, tcl-format
+msgid ""
+"\n"
+"* Untracked file clipped here by %s.\n"
+"* To see the entire file, use an external editor.\n"
+msgstr ""
+
+#: lib/diff.tcl:437
msgid "Failed to unstage selected hunk."
msgstr ""
"Fehler beim Herausnehmen des gewählten Kontexts aus der Bereitstellung."
@@ -1559,6 +1629,19 @@ msgstr "Fehler beim Herausnehmen der gewählten Zeile aus der Bereitstellung."
msgid "Failed to stage selected line."
msgstr "Fehler beim Bereitstellen der gewählten Zeile."
+#: lib/encoding.tcl:443
+msgid "Default"
+msgstr "Voreinstellung"
+
+#: lib/encoding.tcl:448
+#, tcl-format
+msgid "System (%s)"
+msgstr "Systemweit (%s)"
+
+#: lib/encoding.tcl:459 lib/encoding.tcl:465
+msgid "Other"
+msgstr "Andere"
+
#: lib/error.tcl:20 lib/error.tcl:114
msgid "error"
msgstr "Fehler"
@@ -1811,7 +1894,12 @@ msgstr ""
"Diese Operation kann nur rückgängig gemacht werden, wenn die\n"
"Zusammenführung erneut gestartet wird."
-#: lib/mergetool.tcl:32
+#: lib/mergetool.tcl:45
+#, tcl-format
+msgid "File %s seems to have unresolved conflicts, still stage?"
+msgstr "Datei »%s« hat nicht aufgelöste Konflikte. Trotzdem bereitstellen?"
+
+#: lib/mergetool.tcl:60
#, tcl-format
msgid "Adding resolution for %s"
msgstr "Auflösung hinzugefügt für %s"
@@ -1868,12 +1956,17 @@ msgstr "Zusammenführungswerkzeug starten..."
msgid "Merge tool failed."
msgstr "Zusammenführungswerkzeug fehlgeschlagen."
-#: lib/mergetool.tcl:353
+#: lib/option.tcl:11
+#, tcl-format
+msgid "Invalid global encoding '%s'"
+msgstr "Ungültige globale Zeichenkodierung »%s«"
+
+#: lib/option.tcl:19
#, tcl-format
-msgid "File %s unchanged, still accept as resolved?"
-msgstr "Datei »%s« unverändert. Trotzdem Konflikt als gelöst akzeptieren?"
+msgid "Invalid repo encoding '%s'"
+msgstr "Ungültige Archiv-Zeichenkodierung »%s«"
-#: lib/option.tcl:95
+#: lib/option.tcl:117
msgid "Restore Defaults"
msgstr "Voreinstellungen wiederherstellen"
@@ -1950,7 +2043,15 @@ msgstr "Textbreite der Versionsbeschreibung"
msgid "New Branch Name Template"
msgstr "Namensvorschlag für neue Zweige"
-#: lib/option.tcl:192
+#: lib/option.tcl:155
+msgid "Default File Contents Encoding"
+msgstr "Vorgestellte Zeichenkodierung"
+
+#: lib/option.tcl:203
+msgid "Change"
+msgstr "Ändern"
+
+#: lib/option.tcl:230
msgid "Spelling Dictionary:"
msgstr "Wörterbuch Rechtschreibprüfung:"
@@ -1975,9 +2076,85 @@ msgstr "Einstellungen"
msgid "Failed to completely save options:"
msgstr "Optionen konnten nicht gespeichert werden:"
+#: lib/remote_add.tcl:19
+msgid "Add Remote"
+msgstr "Anderes Archiv hinzufügen"
+
+#: lib/remote_add.tcl:24
+msgid "Add New Remote"
+msgstr "Neues anderes Archiv hinzufügen"
+
+#: lib/remote_add.tcl:28
+msgid "Add"
+msgstr "Hinzufügen"
+
+#: lib/remote_add.tcl:37
+msgid "Remote Details"
+msgstr "Einzelheiten des anderen Archivs"
+
+#: lib/remote_add.tcl:50
+msgid "Location:"
+msgstr "Adresse:"
+
+#: lib/remote_add.tcl:62
+msgid "Further Action"
+msgstr "Weitere Aktion jetzt"
+
+#: lib/remote_add.tcl:65
+msgid "Fetch Immediately"
+msgstr "Gleich anfordern"
+
+#: lib/remote_add.tcl:71
+msgid "Initialize Remote Repository and Push"
+msgstr "Anderes Archiv initialisieren und dahin versenden"
+
+#: lib/remote_add.tcl:77
+msgid "Do Nothing Else Now"
+msgstr "Nichts tun"
+
+#: lib/remote_add.tcl:101
+#, fuzzy
+msgid "Please supply a remote name."
+msgstr "Bitte geben Sie einen Zweignamen an."
+
+#: lib/remote_add.tcl:114
+#, fuzzy, tcl-format
+msgid "'%s' is not an acceptable remote name."
+msgstr "»%s« ist kein zulässiger Zweigname."
+
+#: lib/remote_add.tcl:125
+#, fuzzy, tcl-format
+msgid "Failed to add remote '%s' of location '%s'."
+msgstr "Fehler beim Umbenennen von »%s«."
+
+#: lib/remote_add.tcl:133 lib/transport.tcl:6
+#, tcl-format
+msgid "fetch %s"
+msgstr "»%s« anfordern"
+
+#: lib/remote_add.tcl:134
+#, fuzzy, tcl-format
+msgid "Fetching the %s"
+msgstr "Änderungen »%s« von »%s« anfordern"
+
+#: lib/remote_add.tcl:157
+#, tcl-format
+msgid "Do not know how to initialize repository at location '%s'."
+msgstr "Initialisieren eines anderen Archivs an Adresse »%s« ist nicht möglich."
+
+#: lib/remote_add.tcl:163 lib/transport.tcl:25 lib/transport.tcl:71
+#, tcl-format
+msgid "push %s"
+msgstr "»%s« versenden..."
+
+#: lib/remote_add.tcl:164
+#, tcl-format
+msgid "Setting up the %s (at %s)"
+msgstr "Einrichten von »%s« an »%s«"
+
#: lib/remote_branch_delete.tcl:29 lib/remote_branch_delete.tcl:34
-msgid "Delete Remote Branch"
-msgstr "Zweig in anderem Projektarchiv löschen"
+msgid "Delete Branch Remotely"
+msgstr "Zweig in anderem Archiv löschen"
#: lib/remote_branch_delete.tcl:47
msgid "From Repository"
@@ -1988,8 +2165,8 @@ msgid "Remote:"
msgstr "Anderes Archiv:"
#: lib/remote_branch_delete.tcl:66 lib/transport.tcl:138
-msgid "Arbitrary URL:"
-msgstr "Archiv-URL:"
+msgid "Arbitrary Location:"
+msgstr "Adresse:"
#: lib/remote_branch_delete.tcl:84
msgid "Branches"
@@ -2061,7 +2238,11 @@ msgstr "Kein Projektarchiv ausgewählt."
msgid "Scanning %s..."
msgstr "»%s« laden..."
-#: lib/remote.tcl:165
+#: lib/remote.tcl:163
+msgid "Remove Remote"
+msgstr "Anderes Archiv entfernen"
+
+#: lib/remote.tcl:168
msgid "Prune from"
msgstr "Aufräumen von"
@@ -2073,6 +2254,22 @@ msgstr "Anfordern von"
msgid "Push to"
msgstr "Versenden nach"
+#: lib/search.tcl:21
+msgid "Find:"
+msgstr "Suchen:"
+
+#: lib/search.tcl:22
+msgid "Next"
+msgstr "Nächster"
+
+#: lib/search.tcl:23
+msgid "Prev"
+msgstr "Voriger"
+
+#: lib/search.tcl:24
+msgid "Case-Sensitive"
+msgstr ""
+
#: lib/shortcut.tcl:20 lib/shortcut.tcl:61
msgid "Cannot write shortcut:"
msgstr "Fehler beim Schreiben der Verknüpfung:"
@@ -2123,11 +2320,6 @@ msgstr "Rechtschreibprüfung fehlgeschlagen"
msgid "%s ... %*i of %*i %s (%3i%%)"
msgstr "%s ... %*i von %*i %s (%3i%%)"
-#: lib/transport.tcl:6
-#, tcl-format
-msgid "fetch %s"
-msgstr "»%s« anfordern"
-
#: lib/transport.tcl:7
#, tcl-format
msgid "Fetching new changes from %s"
@@ -2143,11 +2335,6 @@ msgstr "Aufräumen von »%s«"
msgid "Pruning tracking branches deleted from %s"
msgstr "Übernahmezweige aufräumen und entfernen, die in »%s« gelöscht wurden"
-#: lib/transport.tcl:25 lib/transport.tcl:71
-#, tcl-format
-msgid "push %s"
-msgstr "»%s« versenden..."
-
#: lib/transport.tcl:26
#, tcl-format
msgid "Pushing changes to %s"
--
1.6.0.rc1.34.g0fe8c
^ permalink raw reply related
* From Perforce to Git
From: Brandon @ 2008-10-25 21:18 UTC (permalink / raw)
To: git
I'm trying to make a comprehensive comparison of Perforce and Git
features. There are two things I currently can't find:
1) "Who's editing what"
It's been documented that git can help developers communicate who
is editing what at any given time like perforce. (assuming there is a
central repositry) Has anyone seen an example of scripts to do this?
References:
http://www-cs-students.stanford.edu/~blynn/gitmagic/ch07.html (Who's
editing what)
"To view "pending" changes a la P4 C<git cherry> or C<git log> can be used on
someone else's branch, but their changes must be published."
- http://www.nntp.perl.org/group/perl.perl5.porters/2008/09/msg139661.html
2) Symlinks to checkout partial repository
I believe I read symlinks could be used to checkout part of a
repository. Is this true? any references? I imagine submodules is the
preferred way of doing this, and "narrow" or "partial" or "sparse"
checkouts are under development
(http://kerneltrap.org/mailarchive/git/2008/9/14/3292714), but I'm
still interested in learning this solution.
any direction would be appreciated,
-brandon
^ permalink raw reply
* Re: [PATCH 4/7] textconv: don't convert for every operation
From: Junio C Hamano @ 2008-10-25 23:35 UTC (permalink / raw)
To: Jeff King; +Cc: Johannes Sixt, Matthieu Moy, git
In-Reply-To: <20081025193554.GA27457@coredump.intra.peff.net>
Jeff King <peff@peff.net> writes:
> I will re-roll my latest series according to your recommendation
> (unless you are set on reverting the first part; if so, please tell me
> asap so I can work under that assumption).
No, reverting and reapplying is more work than incremental updates.
Please refine on top of what's already in.
^ permalink raw reply
* From Perforce to Git
From: David Symonds @ 2008-10-25 23:41 UTC (permalink / raw)
To: Brandon; +Cc: git
In-Reply-To: <ee77f5c20810251640q4b40d524n7271a0dfa11ebef8@mail.gmail.com>
On Sat, Oct 25, 2008 at 2:18 PM, Brandon <siamesedream01@gmail.com> wrote:
> I'm trying to make a comprehensive comparison of Perforce and Git
> features. There are two things I currently can't find:
>
> 1) "Who's editing what"
> It's been documented that git can help developers communicate who
> is editing what at any given time like perforce. (assuming there is a
> central repositry) Has anyone seen an example of scripts to do this?
That's the primary feature of Perforce that kills its scalability once
you get past a few hundred developers; it bloats the metadata too
much. When you're using Git, there's really little point in using it,
since you don't declare what files you are going to be editing, and
you can find out other people's changes at merge time at your leisure
(not just when *you* want to commit).
> 2) Symlinks to checkout partial repository
> I believe I read symlinks could be used to checkout part of a
> repository. Is this true? any references? I imagine submodules is the
> preferred way of doing this, and "narrow" or "partial" or "sparse"
> checkouts are under development
I don't think so. You could use symlinks to *simulate* a bigger
repository that is actually made up of smaller repositories.
Dave.
^ permalink raw reply
* Re: [PATCH 4/7] textconv: don't convert for every operation
From: Junio C Hamano @ 2008-10-25 23:48 UTC (permalink / raw)
To: Jeff King; +Cc: Johannes Sixt, Matthieu Moy, git
In-Reply-To: <20081025193554.GA27457@coredump.intra.peff.net>
Another place that would benefit from ALLOW_TEXTCONV is the function
wt_status_print_verbose() in wt-status.c, where we generate preview diff
for "git commit -v". The output from that function is purely for human
consumption and does not have to be applicable.
^ permalink raw reply
* Re: Fwd: git status options feature suggestion
From: Junio C Hamano @ 2008-10-26 1:47 UTC (permalink / raw)
To: Jeff King; +Cc: Michael J Gruber, Johannes Schindelin, Caleb Cushing, git
In-Reply-To: <7v1vymgrom.fsf@gitster.siamese.dyndns.org>
Junio C Hamano <gitster@pobox.com> writes:
> Jeff King <peff@peff.net> writes:
>
>> I remember a long time ago you started on a parallel diff walker that
>> could diff the working tree, the index, and a tree at once. Do you
>> remember the issues with it?
>
> Sorry, I don't.
>
>> I think that would be the right tool here to show each file only once,
>> but with multiple status flags. Something like:
>>
>> A M foo
>>
>> to show that "foo" has been added since the last commit, but there are
>> modifications in the working tree that have not yet been staged.
>
> One thing to keep in mind is what to do when you would want to detect
> renames. The parallel walk would be Ok but between HEAD and index there
> could be renames involved, and at that point it would get quite tricky.
> Once the index is in-core, I think it hurts us much to walk HEAD vs index
> and index vs working tree in separate passes.
>
> I think it is perfectly fine to run the diff-index first, and keep the
> result from it in a string_list, and then run "diff-files" and annotate
> the string_list with the output from it.
>
> Something like...
Because I was bored thinking about what to talk about in Gittogether and
lacked enough concentration to do anything productive, I did this that:
(1) introduces the "find and summarize changes in a single string list"
infrastructure;
(2) rewrites wt_status_print_{updated,changed} to use it; and
(3) adds "git shortstatus" that does not take any parameter (so it is not
about "preview of commit with the same paths arguments" anymore) to
give the status in:
XsssY PATH1 -> PATH2
format, where X is the diff status between HEAD and the index, sss is the
rename/copy score of the change (if X is rename or copy --- otherwise
it is blank), Y is the diff status between the index and the worktree.
PATH1 is the path in the HEAD, and " -> PATH2" part is shown only when
PATH1 corresponds to a different path in the index/worktree.
This was done primarily for fun and killing-time, so I won't be committing
it to my tree, but it seems to pass all the existing tests.
If you apply this patch with "git apply" (no --index) and then
$ git mv COPYING RENAMING
then you would see:
$ ./git-shortstatus
M Makefile
R100 COPYING -> RENAMING
M builtin-commit.c
M builtin-revert.c
M builtin.h
M git.c
M wt-status.c
M wt-status.h
It is very much welcomed if somebody wants to build on top of this. A few
obvious things, aside from bikeshedding to drop the score value (which I
just did as a sanity check measure and for nothing else --- I won't feel
hurt if we lost that field from the output) and such are:
* We can also rewrite wt_status_print_untracked() using the collected
data by making the collector pay attention to untracked files quite
easily;
* I did not bouther touching wt_status_print_initial() but I think it
should be straightforward to produce its output from the collected
data, as the collector already knows how to handle the initial commit.
Signed-off-by: Junio C Hamano <gitster@pobox.com>
---
Makefile | 1 +
builtin-commit.c | 45 ++++++++++-
builtin-revert.c | 1 +
builtin.h | 1 +
git.c | 1 +
wt-status.c | 240 +++++++++++++++++++++++++++++++++++++++++-------------
wt-status.h | 9 ++
7 files changed, 239 insertions(+), 59 deletions(-)
diff --git c/Makefile w/Makefile
index d6f3695..36afaa3 100644
--- c/Makefile
+++ w/Makefile
@@ -316,6 +316,7 @@ BUILT_INS += git-merge-subtree$X
BUILT_INS += git-peek-remote$X
BUILT_INS += git-repo-config$X
BUILT_INS += git-show$X
+BUILT_INS += git-shortstatus$X
BUILT_INS += git-status$X
BUILT_INS += git-whatchanged$X
diff --git c/builtin-commit.c w/builtin-commit.c
index 93ca496..99c6409 100644
--- c/builtin-commit.c
+++ w/builtin-commit.c
@@ -14,6 +14,7 @@
#include "diffcore.h"
#include "commit.h"
#include "revision.h"
+#include "string-list.h"
#include "wt-status.h"
#include "run-command.h"
#include "refs.h"
@@ -21,7 +22,6 @@
#include "strbuf.h"
#include "utf8.h"
#include "parse-options.h"
-#include "string-list.h"
#include "rerere.h"
#include "unpack-trees.h"
@@ -856,6 +856,49 @@ static int parse_and_validate_options(int argc, const char *argv[],
return argc;
}
+int cmd_shortstatus(int argc, const char **argv, const char *prefix)
+{
+ struct wt_status s;
+ int i;
+
+ read_cache();
+ refresh_cache(REFRESH_QUIET);
+ wt_status_prepare(&s);
+ wt_status_collect_changes(&s);
+ for (i = 0; i < s.change.nr; i++) {
+ struct wt_status_change_data *d;
+ struct string_list_item *it;
+ char pfx[1 + 3 + 1 + 1];
+
+ it = &(s.change.items[i]);
+ d = it->util;
+ switch (d->index_status) {
+ case DIFF_STATUS_COPIED:
+ case DIFF_STATUS_RENAMED:
+ sprintf(pfx, "%c%3d",
+ d->index_status,
+ (int)(d->index_score * 100 / MAX_SCORE));
+ break;
+ case 0:
+ memcpy(pfx, " ", 4);
+ break;
+ default:
+ sprintf(pfx, "%c ", d->index_status);
+ break;
+ }
+ if (!d->worktree_status)
+ pfx[4] = ' ';
+ else
+ pfx[4] = d->worktree_status;
+ pfx[5] = '\0';
+ printf("%s ", pfx);
+ if (d->head_path)
+ printf("%s -> ", d->head_path);
+ printf("%s\n", it->string);
+ }
+ return 0;
+}
+
int cmd_status(int argc, const char **argv, const char *prefix)
{
const char *index_file;
diff --git c/builtin-revert.c w/builtin-revert.c
index 4725540..060453f 100644
--- c/builtin-revert.c
+++ w/builtin-revert.c
@@ -3,6 +3,7 @@
#include "object.h"
#include "commit.h"
#include "tag.h"
+#include "string-list.h"
#include "wt-status.h"
#include "run-command.h"
#include "exec_cmd.h"
diff --git c/builtin.h w/builtin.h
index 1495cf6..f054fc7 100644
--- c/builtin.h
+++ w/builtin.h
@@ -94,6 +94,7 @@ extern int cmd_shortlog(int argc, const char **argv, const char *prefix);
extern int cmd_show(int argc, const char **argv, const char *prefix);
extern int cmd_show_branch(int argc, const char **argv, const char *prefix);
extern int cmd_status(int argc, const char **argv, const char *prefix);
+extern int cmd_shortstatus(int argc, const char **argv, const char *prefix);
extern int cmd_stripspace(int argc, const char **argv, const char *prefix);
extern int cmd_symbolic_ref(int argc, const char **argv, const char *prefix);
extern int cmd_tag(int argc, const char **argv, const char *prefix);
diff --git c/git.c w/git.c
index 89feb0b..55e6cc9 100644
--- c/git.c
+++ w/git.c
@@ -342,6 +342,7 @@ static void handle_internal_command(int argc, const char **argv)
{ "rm", cmd_rm, RUN_SETUP },
{ "send-pack", cmd_send_pack, RUN_SETUP },
{ "shortlog", cmd_shortlog, USE_PAGER },
+ { "shortstatus", cmd_shortstatus, RUN_SETUP | NEED_WORK_TREE },
{ "show-branch", cmd_show_branch, RUN_SETUP },
{ "show", cmd_show, RUN_SETUP | USE_PAGER },
{ "status", cmd_status, RUN_SETUP | NEED_WORK_TREE },
diff --git c/wt-status.c w/wt-status.c
index c3a9cab..3d2287b 100644
--- c/wt-status.c
+++ w/wt-status.c
@@ -1,4 +1,5 @@
#include "cache.h"
+#include "string-list.h"
#include "wt-status.h"
#include "color.h"
#include "object.h"
@@ -56,6 +57,7 @@ void wt_status_prepare(struct wt_status *s)
s->reference = "HEAD";
s->fp = stdout;
s->index_file = get_index_file();
+ s->change.strdup_strings = 1;
}
static void wt_status_print_cached_header(struct wt_status *s)
@@ -98,18 +100,22 @@ static void wt_status_print_trailer(struct wt_status *s)
#define quote_path quote_path_relative
-static void wt_status_print_filepair(struct wt_status *s,
- int t, struct diff_filepair *p)
+static void wt_status_print_change_data(struct wt_status *s,
+ int t,
+ int status,
+ char *one_name,
+ char *two_name,
+ int score)
{
const char *c = color(t);
const char *one, *two;
struct strbuf onebuf = STRBUF_INIT, twobuf = STRBUF_INIT;
- one = quote_path(p->one->path, -1, &onebuf, s->prefix);
- two = quote_path(p->two->path, -1, &twobuf, s->prefix);
+ one = quote_path(one_name, -1, &onebuf, s->prefix);
+ two = quote_path(two_name, -1, &twobuf, s->prefix);
color_fprintf(s->fp, color(WT_STATUS_HEADER), "#\t");
- switch (p->status) {
+ switch (status) {
case DIFF_STATUS_ADDED:
color_fprintf(s->fp, c, "new file: %s", one);
break;
@@ -135,56 +141,13 @@ static void wt_status_print_filepair(struct wt_status *s,
color_fprintf(s->fp, c, "unmerged: %s", one);
break;
default:
- die("bug: unhandled diff status %c", p->status);
+ die("bug: unhandled diff status %c", status);
}
fprintf(s->fp, "\n");
strbuf_release(&onebuf);
strbuf_release(&twobuf);
}
-static void wt_status_print_updated_cb(struct diff_queue_struct *q,
- struct diff_options *options,
- void *data)
-{
- struct wt_status *s = data;
- int shown_header = 0;
- int i;
- for (i = 0; i < q->nr; i++) {
- if (q->queue[i]->status == 'U')
- continue;
- if (!shown_header) {
- wt_status_print_cached_header(s);
- s->commitable = 1;
- shown_header = 1;
- }
- wt_status_print_filepair(s, WT_STATUS_UPDATED, q->queue[i]);
- }
- if (shown_header)
- wt_status_print_trailer(s);
-}
-
-static void wt_status_print_changed_cb(struct diff_queue_struct *q,
- struct diff_options *options,
- void *data)
-{
- struct wt_status *s = data;
- int i;
- if (q->nr) {
- int has_deleted = 0;
- s->workdir_dirty = 1;
- for (i = 0; i < q->nr; i++)
- if (q->queue[i]->status == DIFF_STATUS_DELETED) {
- has_deleted = 1;
- break;
- }
- wt_status_print_dirty_header(s, has_deleted);
- }
- for (i = 0; i < q->nr; i++)
- wt_status_print_filepair(s, WT_STATUS_CHANGED, q->queue[i]);
- if (q->nr)
- wt_status_print_trailer(s);
-}
-
static void wt_status_print_initial(struct wt_status *s)
{
int i;
@@ -205,13 +168,80 @@ static void wt_status_print_initial(struct wt_status *s)
strbuf_release(&buf);
}
-static void wt_status_print_updated(struct wt_status *s)
+static void wt_status_collect_changed_cb(struct diff_queue_struct *q,
+ struct diff_options *options,
+ void *data)
+{
+ struct wt_status *s = data;
+ int i;
+
+ if (!q->nr)
+ return;
+ s->workdir_dirty = 1;
+ for (i = 0; i < q->nr; i++) {
+ struct diff_filepair *p;
+ struct string_list_item *it;
+ struct wt_status_change_data *d;
+
+ p = q->queue[i];
+
+ d = xcalloc(1, sizeof(*d));
+ d->worktree_status = p->status;
+ it = string_list_insert(p->one->path, &s->change);
+ it->util = d;
+ }
+}
+
+static void wt_status_collect_updated_cb(struct diff_queue_struct *q,
+ struct diff_options *options,
+ void *data)
+{
+ struct wt_status *s = data;
+ int i;
+
+ for (i = 0; i < q->nr; i++) {
+ struct diff_filepair *p;
+ struct string_list_item *it;
+ struct wt_status_change_data *d;
+
+ p = q->queue[i];
+ it = string_list_insert(p->two->path, &s->change);
+ d = it->util;
+ if (!d) {
+ d = xcalloc(1, sizeof(*d));
+ it->util = d;
+ }
+ d->index_status = p->status;
+ switch (p->status) {
+ case DIFF_STATUS_COPIED:
+ case DIFF_STATUS_RENAMED:
+ d->head_path = xstrdup(p->one->path);
+ d->index_score = p->score;
+ break;
+ }
+ }
+}
+
+static void wt_status_collect_changes_worktree(struct wt_status *s)
+{
+ struct rev_info rev;
+
+ init_revisions(&rev, NULL);
+ setup_revisions(0, NULL, &rev, NULL);
+ rev.diffopt.output_format |= DIFF_FORMAT_CALLBACK;
+ rev.diffopt.format_callback = wt_status_collect_changed_cb;
+ rev.diffopt.format_callback_data = s;
+ run_diff_files(&rev, 0);
+}
+
+static void wt_status_collect_changes_index(struct wt_status *s)
{
struct rev_info rev;
+
init_revisions(&rev, NULL);
setup_revisions(0, NULL, &rev, s->reference);
rev.diffopt.output_format |= DIFF_FORMAT_CALLBACK;
- rev.diffopt.format_callback = wt_status_print_updated_cb;
+ rev.diffopt.format_callback = wt_status_collect_updated_cb;
rev.diffopt.format_callback_data = s;
rev.diffopt.detect_rename = 1;
rev.diffopt.rename_limit = 200;
@@ -219,15 +249,107 @@ static void wt_status_print_updated(struct wt_status *s)
run_diff_index(&rev, 1);
}
+static void wt_status_collect_changes_initial(struct wt_status *s)
+{
+ int i;
+
+ for (i = 0; i < active_nr; i++) {
+ struct string_list_item *it;
+ struct wt_status_change_data *d;
+
+ it = string_list_insert(active_cache[i]->name, &s->change);
+ d = it->util;
+ if (!d) {
+ d = xcalloc(1, sizeof(*d));
+ it->util = d;
+ }
+ d->index_status = DIFF_STATUS_ADDED;
+ }
+}
+
+void wt_status_collect_changes(struct wt_status *s)
+{
+ wt_status_collect_changes_worktree(s);
+
+ if (s->is_initial)
+ wt_status_collect_changes_initial(s);
+ else
+ wt_status_collect_changes_index(s);
+}
+
+static void wt_status_print_updated(struct wt_status *s)
+{
+ int shown_header = 0;
+ int i;
+
+ for (i = 0; i < s->change.nr; i++) {
+ struct wt_status_change_data *d;
+ struct string_list_item *it;
+ it = &(s->change.items[i]);
+ d = it->util;
+ if (!d->index_status)
+ continue;
+ if (!shown_header) {
+ wt_status_print_cached_header(s);
+ s->commitable = 1;
+ shown_header = 1;
+ }
+ wt_status_print_change_data(s, WT_STATUS_UPDATED,
+ d->index_status,
+ d->head_path ? d->head_path : it->string,
+ it->string,
+ d->index_score);
+ }
+ if (shown_header)
+ wt_status_print_trailer(s);
+}
+
+/*
+ * -1 : has delete
+ * 0 : no change
+ * 1 : some change but no delete
+ */
+static int wt_status_check_worktree_changes(struct wt_status *s)
+{
+ int i;
+ int changes = 0;
+
+ for (i = 0; i < s->change.nr; i++) {
+ struct wt_status_change_data *d;
+ d = s->change.items[i].util;
+ if (!d->worktree_status)
+ continue;
+ changes = 1;
+ if (d->worktree_status == DIFF_STATUS_DELETED)
+ return -1;
+ }
+ return changes;
+}
+
static void wt_status_print_changed(struct wt_status *s)
{
- struct rev_info rev;
- init_revisions(&rev, "");
- setup_revisions(0, NULL, &rev, NULL);
- rev.diffopt.output_format |= DIFF_FORMAT_CALLBACK;
- rev.diffopt.format_callback = wt_status_print_changed_cb;
- rev.diffopt.format_callback_data = s;
- run_diff_files(&rev, 0);
+ int i;
+ int worktree_changes = wt_status_check_worktree_changes(s);
+
+ if (!worktree_changes)
+ return;
+
+ wt_status_print_dirty_header(s, worktree_changes < 0);
+
+ for (i = 0; i < s->change.nr; i++) {
+ struct wt_status_change_data *d;
+ struct string_list_item *it;
+ it = &(s->change.items[i]);
+ d = it->util;
+ if (!d->worktree_status)
+ continue;
+ wt_status_print_change_data(s, WT_STATUS_CHANGED,
+ d->worktree_status,
+ it->string,
+ it->string,
+ 0);
+ }
+ wt_status_print_trailer(s);
}
static void wt_status_print_submodule_summary(struct wt_status *s)
@@ -347,6 +469,8 @@ void wt_status_print(struct wt_status *s)
wt_status_print_tracking(s);
}
+ wt_status_collect_changes(s);
+
if (s->is_initial) {
color_fprintf_ln(s->fp, color(WT_STATUS_HEADER), "#");
color_fprintf_ln(s->fp, color(WT_STATUS_HEADER), "# Initial commit");
diff --git c/wt-status.h w/wt-status.h
index 78add09..00508c3 100644
--- c/wt-status.h
+++ w/wt-status.h
@@ -18,6 +18,13 @@ enum untracked_status_type {
};
extern enum untracked_status_type show_untracked_files;
+struct wt_status_change_data {
+ int worktree_status;
+ int index_status;
+ int index_score;
+ char *head_path;
+};
+
struct wt_status {
int is_initial;
char *branch;
@@ -33,6 +40,7 @@ struct wt_status {
const char *index_file;
FILE *fp;
const char *prefix;
+ struct string_list change;
};
int git_status_config(const char *var, const char *value, void *cb);
@@ -40,5 +48,6 @@ extern int wt_status_use_color;
extern int wt_status_relative_paths;
void wt_status_prepare(struct wt_status *s);
void wt_status_print(struct wt_status *s);
+void wt_status_collect_changes(struct wt_status *s);
#endif /* STATUS_H */
^ permalink raw reply related
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