* [PATCH] Support printing diffs in the raw and patch format at once
From: Petr Baudis @ 2006-04-10 23:55 UTC (permalink / raw)
To: Junio C Hamano; +Cc: git
This is required when using cg-Xfollowrenames as a backend for
a tool which wants to show the end-user patches; parsing patches
properly is a nightmare, so we need to receive the diff in the
raw diff format from git-diff-tree, while also receiving the diff
in the patch format for further processing by the frontend.
This patch adds a -P option which is similar to the -p option
and achieves this. First the raw diff format is printed, then
a line terminator and then the patch.
It is fairly simple and should be straightforward, so it would be
great if this could yet make it to 1.3.0, or cg-log patch output
would have to stay with broken rename detection until the next Git
major release. :-(
Signed-off-by: Petr Baudis <pasky@suse.cz>
---
Documentation/diff-options.txt | 3 +++
combine-diff.c | 32 ++++++++++++++++++++++++++------
diff-files.c | 2 +-
diff-index.c | 2 +-
diff-stages.c | 2 +-
diff-tree.c | 4 ++--
diff.c | 29 +++++++++++++++++++++--------
diff.h | 3 ++-
8 files changed, 57 insertions(+), 20 deletions(-)
diff --git a/Documentation/diff-options.txt b/Documentation/diff-options.txt
index ec6811c..67c8867 100644
--- a/Documentation/diff-options.txt
+++ b/Documentation/diff-options.txt
@@ -4,6 +4,9 @@
-u::
Synonym for "-p".
+-P::
+ Generate patch but keep also the default raw diff output.
+
-z::
\0 line termination on output
diff --git a/combine-diff.c b/combine-diff.c
index eb0d757..65e110e 100644
--- a/combine-diff.c
+++ b/combine-diff.c
@@ -816,10 +816,33 @@ int show_combined_diff(struct combine_di
default:
case DIFF_FORMAT_PATCH:
+ case DIFF_FORMAT_RAW_PATCH:
return show_patch_diff(p, num_parent, dense, header, opt);
}
}
+const char *show_combined_diffs(struct combine_diff_path *paths,
+ int num_parent, int dense,
+ const char *header, struct diff_options *opt)
+{
+ struct combine_diff_path *p;
+
+ if (opt->output_format == DIFF_FORMAT_RAW_PATCH) {
+ opt->output_format = DIFF_FORMAT_RAW;
+ header = show_combined_diffs(paths, num_parent, dense,
+ header, opt);
+ putchar(opt->line_termination);
+ opt->output_format = DIFF_FORMAT_RAW_PATCH;
+ }
+
+ for (p = paths; p; p = p->next) {
+ if (show_combined_diff(p, num_parent, dense,
+ header, opt))
+ header = NULL;
+ }
+ return header;
+}
+
const char *diff_tree_combined_merge(const unsigned char *sha1,
const char *header, int dense,
struct diff_options *opt)
@@ -849,7 +872,7 @@ const char *diff_tree_combined_merge(con
&diffopts);
diffcore_std(&diffopts);
paths = intersect_paths(paths, i, num_parent);
- diff_flush(&diffopts);
+ diff_flush(&diffopts, 1);
}
/* find out surviving paths */
@@ -858,11 +881,8 @@ const char *diff_tree_combined_merge(con
num_paths++;
}
if (num_paths) {
- for (p = paths; p; p = p->next) {
- if (show_combined_diff(p, num_parent, dense,
- header, opt))
- header = NULL;
- }
+ header = show_combined_diffs(paths, num_parent, dense,
+ header, opt);
}
/* Clean things up */
diff --git a/diff-files.c b/diff-files.c
index 3e7f5f1..4e2e5cb 100644
--- a/diff-files.c
+++ b/diff-files.c
@@ -208,6 +208,6 @@ int main(int argc, const char **argv)
ce->name);
}
diffcore_std(&diff_options);
- diff_flush(&diff_options);
+ diff_flush(&diff_options, 1);
return 0;
}
diff --git a/diff-index.c b/diff-index.c
index e376d65..dade539 100644
--- a/diff-index.c
+++ b/diff-index.c
@@ -248,6 +248,6 @@ int main(int argc, const char **argv)
ret = diff_cache(active_cache, active_nr, pathspec);
diffcore_std(&diff_options);
- diff_flush(&diff_options);
+ diff_flush(&diff_options, 1);
return ret;
}
diff --git a/diff-stages.c b/diff-stages.c
index dcd20e7..fa146a9 100644
--- a/diff-stages.c
+++ b/diff-stages.c
@@ -99,6 +99,6 @@ int main(int ac, const char **av)
diff_stages(stage1, stage2, pathspec);
diffcore_std(&diff_options);
- diff_flush(&diff_options);
+ diff_flush(&diff_options, 1);
return 0;
}
diff --git a/diff-tree.c b/diff-tree.c
index d1265d7..5327df8 100644
--- a/diff-tree.c
+++ b/diff-tree.c
@@ -23,7 +23,7 @@ static int call_diff_flush(void)
if (diff_queue_is_empty()) {
int saved_fmt = diff_options.output_format;
diff_options.output_format = DIFF_FORMAT_NO_OUTPUT;
- diff_flush(&diff_options);
+ diff_flush(&diff_options, 1);
diff_options.output_format = saved_fmt;
return 0;
}
@@ -32,7 +32,7 @@ static int call_diff_flush(void)
printf("%s%c", header, diff_options.line_termination);
header = NULL;
}
- diff_flush(&diff_options);
+ diff_flush(&diff_options, 1);
return 1;
}
diff --git a/diff.c b/diff.c
index 2fa285a..f57d82e 100644
--- a/diff.c
+++ b/diff.c
@@ -862,6 +862,8 @@ int diff_opt_parse(struct diff_options *
const char *arg = av[0];
if (!strcmp(arg, "-p") || !strcmp(arg, "-u"))
options->output_format = DIFF_FORMAT_PATCH;
+ else if (!strcmp(arg, "-P"))
+ options->output_format = DIFF_FORMAT_RAW_PATCH;
else if (!strcmp(arg, "-z"))
options->line_termination = 0;
else if (!strncmp(arg, "-l", 2))
@@ -1270,7 +1272,7 @@ static void diff_resolve_rename_copy(voi
diff_debug_queue("resolve-rename-copy done", q);
}
-void diff_flush(struct diff_options *options)
+void diff_flush(struct diff_options *options, int shall_free)
{
struct diff_queue_struct *q = &diff_queued_diff;
int i;
@@ -1278,6 +1280,13 @@ void diff_flush(struct diff_options *opt
int diff_output_format = options->output_format;
int line_termination = options->line_termination;
+ if (diff_output_format == DIFF_FORMAT_RAW_PATCH) {
+ options->output_format = DIFF_FORMAT_RAW;
+ diff_flush(options, 0);
+ putchar(options->line_termination);
+ options->output_format = DIFF_FORMAT_RAW_PATCH;
+ }
+
if (!line_termination)
inter_name_termination = 0;
@@ -1292,15 +1301,16 @@ void diff_flush(struct diff_options *opt
break;
default:
switch (diff_output_format) {
- case DIFF_FORMAT_PATCH:
- diff_flush_patch(p, options);
- break;
case DIFF_FORMAT_RAW:
case DIFF_FORMAT_NAME_STATUS:
diff_flush_raw(p, line_termination,
inter_name_termination,
options);
break;
+ case DIFF_FORMAT_PATCH:
+ case DIFF_FORMAT_RAW_PATCH:
+ diff_flush_patch(p, options);
+ break;
case DIFF_FORMAT_NAME:
diff_flush_name(p,
inter_name_termination,
@@ -1310,11 +1320,14 @@ void diff_flush(struct diff_options *opt
break;
}
}
- diff_free_filepair(p);
+ if (shall_free)
+ diff_free_filepair(p);
}
- free(q->queue);
- q->queue = NULL;
- q->nr = q->alloc = 0;
+ if (shall_free) {
+ free(q->queue);
+ q->queue = NULL;
+ q->nr = q->alloc = 0;
+ }
}
static void diffcore_apply_filter(const char *filter)
diff --git a/diff.h b/diff.h
index a02ef28..a2dacac 100644
--- a/diff.h
+++ b/diff.h
@@ -135,8 +135,9 @@ #define DIFF_FORMAT_PATCH 2
#define DIFF_FORMAT_NO_OUTPUT 3
#define DIFF_FORMAT_NAME 4
#define DIFF_FORMAT_NAME_STATUS 5
+#define DIFF_FORMAT_RAW_PATCH 6
-extern void diff_flush(struct diff_options*);
+extern void diff_flush(struct diff_options *, int shall_free);
/* diff-raw status letters */
#define DIFF_STATUS_ADDED 'A'
^ permalink raw reply related
* Re: [PATCH] git log [diff-tree options]...
From: Linus Torvalds @ 2006-04-10 23:54 UTC (permalink / raw)
To: Junio C Hamano; +Cc: git
In-Reply-To: <7vodz980az.fsf@assigned-by-dhcp.cox.net>
On Mon, 10 Apr 2006, Junio C Hamano wrote:
> >
> > and I think we'd likely want to have some way to select the output.
> > Probably with the path-limited diff being the default (that's what
> > "git-whatchanged" does), but perhaps with "--full-diff" showing the whole
> > commit diff (which is what "gitk" does).
>
> Yes, but it turns out it is a bit tricky, given that the way
> tree-diff.c is written it pretty much assumes the same pathspec
> is used for diff operation during the lifetime of the process.
Hmm.. The hacky approach would seem to be to just call
"diff_tree_setup_paths()" just before doing the diff (and re-set it
afterwards). That should work, I don't think we keep any real state
around.
> I think we should move (nr_paths, pathlens and paths) to struct
> diff_options. Two patches to follow shortly.
That certainly seems to be the cleanest option. Not just because it should
solve this problem, but because it's also what looks most natural anyway
(and matches the "struct revs" approach).
Linus
^ permalink raw reply
* [PATCH] git log --full-diff
From: Junio C Hamano @ 2006-04-10 23:44 UTC (permalink / raw)
To: git; +Cc: Linus Torvalds
In-Reply-To: <7vodz980az.fsf@assigned-by-dhcp.cox.net>
Without this flag, "git log -p paths..." shows commits that
touch the specified paths, and diffs about the same specified
paths. With this, the full diff is shown for commits that touch
the specified paths.
Signed-off-by: Junio C Hamano <junkio@cox.net>
---
git.c | 13 ++++++++++++-
1 files changed, 12 insertions(+), 1 deletions(-)
fd3ed3d9667e034b90aad02b4f9e5efcc61f1ce3
diff --git a/git.c b/git.c
index 8776088..ad896da 100644
--- a/git.c
+++ b/git.c
@@ -288,7 +288,9 @@ static int cmd_log(int argc, const char
int abbrev_commit = 0;
const char *commit_prefix = "commit ";
struct log_tree_opt opt;
+ int shown = 0;
int do_diff = 0;
+ int full_diff = 0;
init_log_tree_opt(&opt);
argc = setup_revisions(argc, argv, &rev, "HEAD");
@@ -315,6 +317,10 @@ static int cmd_log(int argc, const char
else if (40 < abbrev)
abbrev = 40;
}
+ else if (!strcmp(arg, "--full-diff")) {
+ do_diff = 1;
+ full_diff = 1;
+ }
else {
int cnt = log_tree_opt_parse(&opt, argv+1, argc-1);
if (0 < cnt) {
@@ -328,6 +334,7 @@ static int cmd_log(int argc, const char
argc--; argv++;
}
+
if (do_diff) {
opt.diffopt.abbrev = abbrev;
opt.verbose_header = 0;
@@ -339,12 +346,16 @@ static int cmd_log(int argc, const char
opt.diffopt.output_format = DIFF_FORMAT_PATCH;
if (opt.diffopt.output_format == DIFF_FORMAT_PATCH)
opt.diffopt.recursive = 1;
+ if (!full_diff && rev.prune_data)
+ diff_tree_setup_paths(rev.prune_data, &opt.diffopt);
diff_setup_done(&opt.diffopt);
}
prepare_revision_walk(&rev);
setup_pager();
while ((commit = get_revision(&rev)) != NULL) {
+ if (commit_format != CMIT_FMT_ONELINE && shown)
+ putchar('\n');
fputs(commit_prefix, stdout);
if (abbrev_commit && abbrev)
fputs(find_unique_abbrev(commit->object.sha1, abbrev),
@@ -377,9 +388,9 @@ static int cmd_log(int argc, const char
pretty_print_commit(commit_format, commit, ~0, buf,
LOGSIZE, abbrev);
printf("%s\n", buf);
-
if (do_diff)
log_tree_commit(&opt, commit);
+ shown = 1;
}
free(buf);
return 0;
--
1.3.0.rc3.g910a
^ permalink raw reply related
* [PATCH] tree-diff: do not assume we use only one pathspec
From: Junio C Hamano @ 2006-04-10 23:43 UTC (permalink / raw)
To: git; +Cc: Linus Torvalds
In-Reply-To: <7vodz980az.fsf@assigned-by-dhcp.cox.net>
The way tree-diff was set up assumed we would use only one set
of pathspec during the entire life of the program. Move the
pathspec related static variables out to diff_options structure
so that we can filter commits with one set of paths while show
the actual diffs using different set of paths.
I suspect this breaks blame.c, and makes "git log paths..." to
default to the --full-diff, the latter of which is dealt with
the next commit.
Signed-off-by: Junio C Hamano <junkio@cox.net>
---
diff-tree.c | 2 +-
diff.h | 6 +++++-
revision.c | 2 +-
tree-diff.c | 46 +++++++++++++++++++++++++---------------------
4 files changed, 32 insertions(+), 24 deletions(-)
be7b412689f723a1008b40712d9f0b96773ad81a
diff --git a/diff-tree.c b/diff-tree.c
index 2a088d1..2b79dd0 100644
--- a/diff-tree.c
+++ b/diff-tree.c
@@ -120,7 +120,7 @@ int main(int argc, const char **argv)
if (opt->diffopt.output_format == DIFF_FORMAT_PATCH)
opt->diffopt.recursive = 1;
- diff_tree_setup_paths(get_pathspec(prefix, argv));
+ diff_tree_setup_paths(get_pathspec(prefix, argv), opt);
diff_setup_done(&opt->diffopt);
switch (nr_sha1) {
diff --git a/diff.h b/diff.h
index a02ef28..cc7cc62 100644
--- a/diff.h
+++ b/diff.h
@@ -38,11 +38,15 @@ struct diff_options {
int setup;
int abbrev;
+ int nr_paths;
+ const char **paths;
+ int *pathlens;
change_fn_t change;
add_remove_fn_t add_remove;
};
-extern void diff_tree_setup_paths(const char **paths);
+extern void diff_tree_setup_paths(const char **paths, struct diff_options *);
+extern void diff_tree_release_paths(struct diff_options *);
extern int diff_tree(struct tree_desc *t1, struct tree_desc *t2,
const char *base, struct diff_options *opt);
extern int diff_tree_sha1(const unsigned char *old, const unsigned char *new,
diff --git a/revision.c b/revision.c
index fe26562..634f9a5 100644
--- a/revision.c
+++ b/revision.c
@@ -707,7 +707,7 @@ int setup_revisions(int argc, const char
revs->limited = 1;
if (revs->prune_data) {
- diff_tree_setup_paths(revs->prune_data);
+ diff_tree_setup_paths(revs->prune_data, &diff_opt);
revs->prune_fn = try_to_simplify_commit;
}
diff --git a/tree-diff.c b/tree-diff.c
index 701fbba..1cdf8aa 100644
--- a/tree-diff.c
+++ b/tree-diff.c
@@ -5,11 +5,6 @@ #include "cache.h"
#include "diff.h"
#include "tree.h"
-// What paths are we interested in?
-static int nr_paths = 0;
-static const char **paths = NULL;
-static int *pathlens = NULL;
-
static char *malloc_base(const char *base, const char *path, int pathlen)
{
int baselen = strlen(base);
@@ -72,14 +67,14 @@ static int compare_tree_entry(struct tre
return 0;
}
-static int interesting(struct tree_desc *desc, const char *base)
+static int interesting(struct tree_desc *desc, const char *base, struct diff_options *opt)
{
const char *path;
unsigned mode;
int i;
int baselen, pathlen;
- if (!nr_paths)
+ if (!opt->nr_paths)
return 1;
(void)tree_entry_extract(desc, &path, &mode);
@@ -87,9 +82,9 @@ static int interesting(struct tree_desc
pathlen = strlen(path);
baselen = strlen(base);
- for (i=0; i < nr_paths; i++) {
- const char *match = paths[i];
- int matchlen = pathlens[i];
+ for (i=0; i < opt->nr_paths; i++) {
+ const char *match = opt->paths[i];
+ int matchlen = opt->pathlens[i];
if (baselen >= matchlen) {
/* If it doesn't match, move along... */
@@ -129,7 +124,7 @@ static int interesting(struct tree_desc
static void show_tree(struct diff_options *opt, const char *prefix, struct tree_desc *desc, const char *base)
{
while (desc->size) {
- if (interesting(desc, base))
+ if (interesting(desc, base, opt))
show_entry(opt, prefix, desc, base);
update_tree_entry(desc);
}
@@ -167,11 +162,11 @@ static int show_entry(struct diff_option
int diff_tree(struct tree_desc *t1, struct tree_desc *t2, const char *base, struct diff_options *opt)
{
while (t1->size | t2->size) {
- if (nr_paths && t1->size && !interesting(t1, base)) {
+ if (opt->nr_paths && t1->size && !interesting(t1, base, opt)) {
update_tree_entry(t1);
continue;
}
- if (nr_paths && t2->size && !interesting(t2, base)) {
+ if (opt->nr_paths && t2->size && !interesting(t2, base, opt)) {
update_tree_entry(t2);
continue;
}
@@ -229,19 +224,28 @@ static int count_paths(const char **path
return i;
}
-void diff_tree_setup_paths(const char **p)
+void diff_tree_release_paths(struct diff_options *opt)
{
+ free(opt->pathlens);
+}
+
+void diff_tree_setup_paths(const char **p, struct diff_options *opt)
+{
+ opt->nr_paths = 0;
+ opt->pathlens = NULL;
+ opt->paths = NULL;
+
if (p) {
int i;
- paths = p;
- nr_paths = count_paths(paths);
- if (nr_paths == 0) {
- pathlens = NULL;
+ opt->paths = p;
+ opt->nr_paths = count_paths(p);
+ if (opt->nr_paths == 0) {
+ opt->pathlens = NULL;
return;
}
- pathlens = xmalloc(nr_paths * sizeof(int));
- for (i=0; i<nr_paths; i++)
- pathlens[i] = strlen(paths[i]);
+ opt->pathlens = xmalloc(opt->nr_paths * sizeof(int));
+ for (i=0; i < opt->nr_paths; i++)
+ opt->pathlens[i] = strlen(p[i]);
}
}
--
1.3.0.rc3.g910a
^ permalink raw reply related
* Re: [PATCH] git log [diff-tree options]...
From: Junio C Hamano @ 2006-04-10 23:42 UTC (permalink / raw)
To: Linus Torvalds; +Cc: git
In-Reply-To: <Pine.LNX.4.64.0604090950590.9504@g5.osdl.org>
Linus Torvalds <torvalds@osdl.org> writes:
> On Sun, 9 Apr 2006, Junio C Hamano wrote:
>>
>> And this makes "git log" to take common diff-tree options, so
>> that it can be used as "git whatchanged".
>
> I wonder... This all looks fine, but there are actually two different
> "diffs" that can be shown for "git log --diff <pathlimiter>":
>
> - the whole diff for a commit
>
> - the path-limited diff
>
> and I think we'd likely want to have some way to select the output.
> Probably with the path-limited diff being the default (that's what
> "git-whatchanged" does), but perhaps with "--full-diff" showing the whole
> commit diff (which is what "gitk" does).
Yes, but it turns out it is a bit tricky, given that the way
tree-diff.c is written it pretty much assumes the same pathspec
is used for diff operation during the lifetime of the process.
I think we should move (nr_paths, pathlens and paths) to struct
diff_options. Two patches to follow shortly.
^ permalink raw reply
* Re: git-svnimport on OSX?
From: Rutger Nijlunsing @ 2006-04-10 23:00 UTC (permalink / raw)
To: Martin Langhoff; +Cc: Randal L. Schwartz, git
In-Reply-To: <46a038f90604031911y415dd795nc1c8814f80a02ad7@mail.gmail.com>
On Tue, Apr 04, 2006 at 02:11:02PM +1200, Martin Langhoff wrote:
> On 03 Apr 2006 18:04:07 -0700, Randal L. Schwartz <merlyn@stonehenge.com> wrote:
> >
> > Working for anyone? Not working for me, and just wondered if it was me or a
> > known thing. Maybe I'm just holding my mouth wrong, and yes, I have SVN::Core
> > installed. If anyone wants details, I can provide.
>
> I think I tried and gave up on it a month or two ago, but can't
> remember the details. Fink's SVN::Core is too old, and having all the
> SVN toolchain is a pain. What is the problem?
>
> BTW, getting git-svnimport to work normally takes me quite a few tries
> with different options, so OSX may be perfectly innocent this time...
Could you try http://www.wingding.demon.nl/git-svnconvert.rb on
MacOSX? This one doesn't need SVN::Core, and I'm curious on what to
change for MacOSX.
By default it imports all branches it can find (see in file itself):
...
$branch_dirs = %q{
/branches/*
/trunk
}
...
If your layout is different (for example, like
http://svn.perl.org/perl6 where every subdir is a collection of
branches itself), use something like:
...
$branch_dirs = %q{
*/branches/*
*/trunk
}
...
--
Rutger Nijlunsing ---------------------------------- eludias ed dse.nl
never attribute to a conspiracy which can be explained by incompetence
----------------------------------------------------------------------
^ permalink raw reply
* SVN_URL undocumented
From: Pavel Roskin @ 2006-04-10 21:22 UTC (permalink / raw)
To: Eric Wong; +Cc: git
Hello, Eric!
I'm trying to use git-svn, but the documentation seems to be quite
unclear. I'm using current git-svn from the git repository.
I'm running "git-svn init" in a Subversion working directory:
$ git-svn init
SVN repository location required
at /home/proski/bin/git-svn line 223
main::init() called at /home/proski/bin/git-svn line 104
The help shown by git-svn without arguments doesn't say anything about
arguments for "init", unlike other subcommands. I'm assuming that
"git-svn init" is not taking any arguments.
The manual page doesn't say anything about arguments, but it mentions
that "the SVN_URL must be specified at this point". This statement is
unclear to me.
There are several references to SVN_URL in the manual, but there is no
description what it is. Is it supposed to be an environment variable,
or an undocumented argument, or is it taken from "svn info" output?
The environment variable has no effect:
$ SVN_URL=http://svn.madwifi.org/trunk git-svn init
SVN repository location required
at /home/proski/bin/git-svn line 223
main::init() called at /home/proski/bin/git-svn line 104
Looking at the sources, it looks like that SVN_URL is an undocumented
argument for "git-cvs init". "git-svn fetch" appears to be taking that
value from the git repository, but it also takes care to protect the
original value (I have no idea where it can come from).
One of the "basic examples" further in the manual confirms that SVN_URL
is set on the command line:
git-svn init http://svn.foo.org/project/trunk
I believe that the documentation should be updated to describe where
SVN_URL comes from, and what arguments are accepted by "git-svn init".
Basic examples shouldn't recommend using undocumented arguments.
It seems to me that the current documentation describes the internals of
git-svn instead of its user interface. Rather than tell the user that
"FOO must be specified at that point", the documentation should say what
(an how) should (or can) be specified when the command is invoked on the
command line.
Also, it would be great to refer to the "additional fetch arguments" in
the "fetch" description. That section is easy to miss by somebody who
is specifically looking for "fetch arguments".
--
Regards,
Pavel Roskin
^ permalink raw reply
* Re: [PATCH] Implement limited context matching in git-apply.
From: Junio C Hamano @ 2006-04-10 19:29 UTC (permalink / raw)
To: Eric W. Biederman; +Cc: git
In-Reply-To: <m1irphhj1p.fsf_-_@ebiederm.dsl.xmission.com>
ebiederm@xmission.com (Eric W. Biederman) writes:
> If I just loop through all of Andrews patches in order
> and run git-apply --index -C1 I process the entire patchset
> in 1m53s or about 6 patches per second. So running
> git-mailinfo, git-write-tree, git-commit-tree, and
> git-update-ref everytime has a measurable impact,
> and shows things can be speeded up even more.
Although I haven't "read" it, but just only "looked at" it, the
patch looks OK. I haven't managed to start beating on it yet
for time constraints.
If you are dealing with the kernel tree, I suspect most time is
spent on write-tree. Statistically, a typical kernel patch (I
haven't counted the ones in -mm series, but only the ones
actually reacheable from Linus tip) touches only 3 files on
average, so most of the 1,100 tree objects in a typical kernel
tree are computed but found unchanged when write-tree happens.
I suspect we could make a backward incompatible change to the
index file format to record the top-level tree object names
somewhere where normal cache-entry walker would not see. Then
when anybody makes a modification to invalidate that tree
object, mark that tree (or split that tree to read lower level
trees lazily) to force us recompute the tree object.
Theoretically you could do that recursively to record all 1,100
tree objects but that would make the cache slightly larger (say,
by 100kB).
^ permalink raw reply
* Re: [PATCH] Implement limited context matching in git-apply.
From: Eric W. Biederman @ 2006-04-10 18:35 UTC (permalink / raw)
To: Linus Torvalds; +Cc: Junio C Hamano, git
In-Reply-To: <Pine.LNX.4.64.0604100821340.9504@g5.osdl.org>
Linus Torvalds <torvalds@osdl.org> writes:
> On Mon, 10 Apr 2006, Eric W. Biederman wrote:
>>
>> If I just loop through all of Andrews patches in order
>> and run git-apply --index -C1 I process the entire patchset
>> in 1m53s or about 6 patches per second. So running
>> git-mailinfo, git-write-tree, git-commit-tree, and
>> git-update-ref everytime has a measurable impact,
>> and shows things can be speeded up even more.
>
> git-write-tree is actually a fairly expensive operation on the kernel. It
> needs to write the 1000+ tree objects - and while _most_ of them already
> exist (and thus don't actually need to be written out), we need to
> generate the tree object and its SHA1 in order to notice that that is the
> case.
>
> I'm almost certain that 90%+ of the overhead you see is the tree writing,
> not the rest of the scripting.
Well it is easy enough to time. Looking at the timings
going from just git-apply to git-apply && git-write-tree
does seem to about the double the amount of time taken,
or take me to about 4 minutes. With everything else
in there things happen in the 6-7 minute range with
in the hot cache scenario. So write-tree is closer
to 50% of the overhead.
Is it possible to cache the sha1 of unmodified directories?
If we did that we could probe to see if the hash already
existed before we attempted to look for the subdirectories.
The pain would is remembering which directory sha1 are
current. If nothing else we can modify:
remove_cache_entry, and add_file_to_cache to clear
the parent directories cached sha1 when we update an
index entry. But I keep thinking there should
be something more elegant. Like using ce_flags,
or comparing mtime values.
...
Ok taking a quick look at write-tree to see where
the bottle neck is:
I made two modified versions of write-tree.
- git-write-tree-nowritetree which calls return just before calling
write_tree.
- git-write-tree-nosha1write which does everything except call
sha1_file_write.
With just git-apply and git-write-tree-nosha1write it takes
me about 3m:20s to process 2.6.17-rc1-mm2.
With just git-apply and git-write-tree-nowritetree it takes:
real 2m59.985s
user 1m38.353s
sys 0m31.445s
With just git-apply and /bin/true it takes:
real 2m1.581s
user 1m3.169s
sys 0m29.903s
Looking at the individual numbers:
$ time git-write-tree-nowritetree --missing-ok
real 0m0.158s
user 0m0.052s
sys 0m0.008s
$ time git-write-tree-nowritetree --missing-ok
real 0m0.155s
user 0m0.057s
sys 0m0.003s
$ time git-write-tree-nowritetree --missing-ok
real 0m0.065s
user 0m0.057s
sys 0m0.002s
$ time git-write-tree-nowritetree --missing-ok
real 0m0.159s
user 0m0.055s
sys 0m0.005s
$ time git-write-tree-nowritetree --missing-ok
real 0m0.151s
user 0m0.054s
sys 0m0.007s
$ time git-write-tree-nowritetree --missing-ok
real 0m0.154s
user 0m0.056s
sys 0m0.005s
$ time git-write-tree-nosha1write --missing-ok
0000000000000000000000000000000000000000
real 0m0.199s
user 0m0.091s
sys 0m0.008s
$ time git-write-tree-nosha1write --missing-ok
0000000000000000000000000000000000000000
real 0m0.195s
user 0m0.094s
sys 0m0.007s
$ time git-write-tree-nosha1write --missing-ok
0000000000000000000000000000000000000000
real 0m0.198s
user 0m0.092s
sys 0m0.009s
$ time git-write-tree --missing-ok
0ecfe3dbc2e65aa9638c62abf0cf05057c77f884
real 0m0.217s
user 0m0.113s
sys 0m0.012s
$ time git-write-tree
0ecfe3dbc2e65aa9638c62abf0cf05057c77f884
real 0m0.276s
user 0m0.169s
sys 0m0.008s
So at a quick inspection it looks to me like:
About .059s to perform to check for missing files.
About .019s to write the new tree.
About .155s in start up overhead, read_cache, and sanity checks.
So at a first glance it looks like librification to
allow the redundant work to be skipped, is where
the big speed win on my machine would be.
> Your patch looks ok from a quick read-through:
Thanks.
My import of 2.6.17-rc1-mm2 gives exactly the same
result as simply applying Andrews patch. Which while
not definitive hits a lot of interesting cases.
> Acked-by: Linus Torvalds <torvalds@osdl.org>
>
> Linus
^ permalink raw reply
* Re: git-svnimport on OSX?
From: Randal L. Schwartz @ 2006-04-10 14:43 UTC (permalink / raw)
To: Martin Langhoff; +Cc: git
In-Reply-To: <46a038f90604031911y415dd795nc1c8814f80a02ad7@mail.gmail.com>
>>>>> "Martin" == Martin Langhoff <martin.langhoff@gmail.com> writes:
Martin> BTW, getting git-svnimport to work normally takes me quite a few tries
Martin> with different options, so OSX may be perfectly innocent this time...
Well, is there some combination of things that will give me what
http://svn.perl.org/perl6/doc does? Maybe it just resists all attempts. :)
--
Randal L. Schwartz - Stonehenge Consulting Services, Inc. - +1 503 777 0095
<merlyn@stonehenge.com> <URL:http://www.stonehenge.com/merlyn/>
Perl/Unix/security consulting, Technical writing, Comedy, etc. etc.
See PerlTraining.Stonehenge.com for onsite and open-enrollment Perl training!
^ permalink raw reply
* Re: [PATCH] Implement limited context matching in git-apply.
From: Linus Torvalds @ 2006-04-10 15:25 UTC (permalink / raw)
To: Eric W. Biederman; +Cc: Junio C Hamano, git
In-Reply-To: <m1irphhj1p.fsf_-_@ebiederm.dsl.xmission.com>
On Mon, 10 Apr 2006, Eric W. Biederman wrote:
>
> If I just loop through all of Andrews patches in order
> and run git-apply --index -C1 I process the entire patchset
> in 1m53s or about 6 patches per second. So running
> git-mailinfo, git-write-tree, git-commit-tree, and
> git-update-ref everytime has a measurable impact,
> and shows things can be speeded up even more.
git-write-tree is actually a fairly expensive operation on the kernel. It
needs to write the 1000+ tree objects - and while _most_ of them already
exist (and thus don't actually need to be written out), we need to
generate the tree object and its SHA1 in order to notice that that is the
case.
I'm almost certain that 90%+ of the overhead you see is the tree writing,
not the rest of the scripting.
Your patch looks ok from a quick read-through:
Acked-by: Linus Torvalds <torvalds@osdl.org>
Linus
^ permalink raw reply
* [PATCH] Implement limited context matching in git-apply.
From: Eric W. Biederman @ 2006-04-10 9:33 UTC (permalink / raw)
To: Junio C Hamano; +Cc: git
In-Reply-To: <m13bgmht9v.fsf@ebiederm.dsl.xmission.com>
Ok this really should be the good version. The option
handling has been reworked to be automation safe.
Currently to import the -mm tree I have to work around
git-apply by using patch. Because some of Andrews
patches in quilt will only apply with fuzz.
I started out implementing a --fuzz option and then I realized
fuzz is not a very safe concept for an automated system. What
you really want is a minimum number of context lines that must
match. This allows policy to be set without knowing how many
lines of context a patch actually provides. By default
the policy remains to match all provided lines of context.
Allowng git-apply to match a restricted set of context makes
it much easier to import the -mm tree into git. I am still only
processing 1.5 to 1.6 patches a second for the 692 patches in
2.6.17-rc1-mm2 is still painful but it does help.
If I just loop through all of Andrews patches in order
and run git-apply --index -C1 I process the entire patchset
in 1m53s or about 6 patches per second. So running
git-mailinfo, git-write-tree, git-commit-tree, and
git-update-ref everytime has a measurable impact,
and shows things can be speeded up even more.
All of these timings were taking on my poor 700Mhz Athlon
with 512MB of ram. So people with fast machiens should
see much better performance.
When a match is found after the number of context are reduced a
warning is generated. Since this is a rare event and possibly
dangerous this seems to make sense. Unless you are patching
a single file the error message is a little bit terse at
the moment, but it should be easy to go back and fix.
I have also updated the documentation for git-apply to reflect
the new -C option that sets the minimum number of context
lines that must match.
Signed-off-by: Eric W. Biederman <ebiederm@xmission.com>
---
Documentation/git-apply.txt | 8 ++-
apply.c | 121 +++++++++++++++++++++++++++++++++++++------
2 files changed, 111 insertions(+), 18 deletions(-)
6b3a4565b760664a9b72096dd5eea8be9e1d1311
diff --git a/Documentation/git-apply.txt b/Documentation/git-apply.txt
index 1c64a1a..e93ea1f 100644
--- a/Documentation/git-apply.txt
+++ b/Documentation/git-apply.txt
@@ -11,7 +11,7 @@ SYNOPSIS
[verse]
'git-apply' [--stat] [--numstat] [--summary] [--check] [--index] [--apply]
[--no-add] [--index-info] [--allow-binary-replacement] [-z] [-pNUM]
- [--whitespace=<nowarn|warn|error|error-all|strip>]
+ [-CNUM] [--whitespace=<nowarn|warn|error|error-all|strip>]
[<patch>...]
DESCRIPTION
@@ -72,6 +72,12 @@ OPTIONS
-p<n>::
Remove <n> leading slashes from traditional diff paths. The
default is 1.
+
+-C<n>::
+ Ensure at least <n> lines of surrounding context match before
+ and after each change. When fewer lines of surrounding
+ context exist they all most match. By default no context is
+ ever ignored.
--apply::
If you use any of the options marked ``Turns off
diff --git a/apply.c b/apply.c
index 33b4271..147a919 100644
--- a/apply.c
+++ b/apply.c
@@ -32,8 +32,9 @@ static int apply = 1;
static int no_add = 0;
static int show_index_info = 0;
static int line_termination = '\n';
+static unsigned long p_context = -1;
static const char apply_usage[] =
-"git-apply [--stat] [--numstat] [--summary] [--check] [--index] [--apply] [--no-add] [--index-info] [--allow-binary-replacement] [-z] [-pNUM] [--whitespace=<nowarn|warn|error|error-all|strip>] <patch>...";
+"git-apply [--stat] [--numstat] [--summary] [--check] [--index] [--apply] [--no-add] [--index-info] [--allow-binary-replacement] [-z] [-pNUM] [-CNUM] [--whitespace=<nowarn|warn|error|error-all|strip>] <patch>...";
static enum whitespace_eol {
nowarn_whitespace,
@@ -100,6 +101,7 @@ static int max_change, max_len;
static int linenr = 1;
struct fragment {
+ unsigned long leading, trailing;
unsigned long oldpos, oldlines;
unsigned long newpos, newlines;
const char *patch;
@@ -817,12 +819,15 @@ static int parse_fragment(char *line, un
int added, deleted;
int len = linelen(line, size), offset;
unsigned long oldlines, newlines;
+ unsigned long leading, trailing;
offset = parse_fragment_header(line, len, fragment);
if (offset < 0)
return -1;
oldlines = fragment->oldlines;
newlines = fragment->newlines;
+ leading = 0;
+ trailing = 0;
if (patch->is_new < 0) {
patch->is_new = !oldlines;
@@ -860,10 +865,14 @@ static int parse_fragment(char *line, un
case ' ':
oldlines--;
newlines--;
+ if (!deleted && !added)
+ leading++;
+ trailing++;
break;
case '-':
deleted++;
oldlines--;
+ trailing = 0;
break;
case '+':
/*
@@ -887,6 +896,7 @@ static int parse_fragment(char *line, un
}
added++;
newlines--;
+ trailing = 0;
break;
/* We allow "\ No newline at end of file". Depending
@@ -904,6 +914,9 @@ static int parse_fragment(char *line, un
}
if (oldlines || newlines)
return -1;
+ fragment->leading = leading;
+ fragment->trailing = trailing;
+
/* If a fragment ends with an incomplete line, we failed to include
* it in the above loop because we hit oldlines == newlines == 0
* before seeing it.
@@ -1087,7 +1100,7 @@ static int read_old_data(struct stat *st
}
}
-static int find_offset(const char *buf, unsigned long size, const char *fragment, unsigned long fragsize, int line)
+static int find_offset(const char *buf, unsigned long size, const char *fragment, unsigned long fragsize, int line, int *lines)
{
int i;
unsigned long start, backwards, forwards;
@@ -1148,6 +1161,7 @@ static int find_offset(const char *buf,
n = (i >> 1)+1;
if (i & 1)
n = -n;
+ *lines = n;
return try;
}
@@ -1155,6 +1169,33 @@ static int find_offset(const char *buf,
* We should start searching forward and backward.
*/
return -1;
+}
+
+static void remove_first_line(const char **rbuf, int *rsize)
+{
+ const char *buf = *rbuf;
+ int size = *rsize;
+ unsigned long offset;
+ offset = 0;
+ while (offset <= size) {
+ if (buf[offset++] == '\n')
+ break;
+ }
+ *rsize = size - offset;
+ *rbuf = buf + offset;
+}
+
+static void remove_last_line(const char **rbuf, int *rsize)
+{
+ const char *buf = *rbuf;
+ int size = *rsize;
+ unsigned long offset;
+ offset = size - 1;
+ while (offset > 0) {
+ if (buf[--offset] == '\n')
+ break;
+ }
+ *rsize = offset + 1;
}
struct buffer_desc {
@@ -1192,7 +1233,10 @@ static int apply_one_fragment(struct buf
int offset, size = frag->size;
char *old = xmalloc(size);
char *new = xmalloc(size);
+ const char *oldlines, *newlines;
int oldsize = 0, newsize = 0;
+ unsigned long leading, trailing;
+ int pos, lines;
while (size > 0) {
int len = linelen(patch, size);
@@ -1241,23 +1285,59 @@ #ifdef NO_ACCURATE_DIFF
newsize--;
}
#endif
+
+ oldlines = old;
+ newlines = new;
+ leading = frag->leading;
+ trailing = frag->trailing;
+ lines = 0;
+ pos = frag->newpos;
+ for (;;) {
+ offset = find_offset(buf, desc->size, oldlines, oldsize, pos, &lines);
+ if (offset >= 0) {
+ int diff = newsize - oldsize;
+ unsigned long size = desc->size + diff;
+ unsigned long alloc = desc->alloc;
+
+ /* Warn if it was necessary to reduce the number
+ * of context lines.
+ */
+ if ((leading != frag->leading) || (trailing != frag->trailing))
+ fprintf(stderr, "Context reduced to (%ld/%ld) to apply fragment at %d\n",
+ leading, trailing, pos + lines);
+
+ if (size > alloc) {
+ alloc = size + 8192;
+ desc->alloc = alloc;
+ buf = xrealloc(buf, alloc);
+ desc->buffer = buf;
+ }
+ desc->size = size;
+ memmove(buf + offset + newsize, buf + offset + oldsize, size - offset - newsize);
+ memcpy(buf + offset, newlines, newsize);
+ offset = 0;
- offset = find_offset(buf, desc->size, old, oldsize, frag->newpos);
- if (offset >= 0) {
- int diff = newsize - oldsize;
- unsigned long size = desc->size + diff;
- unsigned long alloc = desc->alloc;
-
- if (size > alloc) {
- alloc = size + 8192;
- desc->alloc = alloc;
- buf = xrealloc(buf, alloc);
- desc->buffer = buf;
+ break;
}
- desc->size = size;
- memmove(buf + offset + newsize, buf + offset + oldsize, size - offset - newsize);
- memcpy(buf + offset, new, newsize);
- offset = 0;
+
+ /* Am I at my context limits? */
+ if ((leading <= p_context) && (trailing <= p_context))
+ break;
+ /* Reduce the number of context lines
+ * Reduce both leading and trailing if they are equal
+ * otherwise just reduce the larger context.
+ */
+ if (leading >= trailing) {
+ remove_first_line(&oldlines, &oldsize);
+ remove_first_line(&newlines, &newsize);
+ pos--;
+ leading--;
+ }
+ if (trailing > leading) {
+ remove_last_line(&oldlines, &oldsize);
+ remove_last_line(&newlines, &newsize);
+ trailing--;
+ }
}
free(old);
@@ -1882,6 +1962,7 @@ int main(int argc, char **argv)
for (i = 1; i < argc; i++) {
const char *arg = argv[i];
+ char *end;
int fd;
if (!strcmp(arg, "-")) {
@@ -1943,6 +2024,12 @@ int main(int argc, char **argv)
}
if (!strcmp(arg, "-z")) {
line_termination = 0;
+ continue;
+ }
+ if (!strncmp(arg, "-C", 2)) {
+ p_context = strtoul(arg + 2, &end, 0);
+ if (*end != '\0')
+ die("unrecognized context count '%s'", arg + 2);
continue;
}
if (!strncmp(arg, "--whitespace=", 13)) {
--
1.3-rc3.GIT
^ permalink raw reply related
* Re: git commit broken ?
From: Franck Bui-Huu @ 2006-04-10 8:24 UTC (permalink / raw)
To: Junio C Hamano; +Cc: git
In-Reply-To: <7vhd51alti.fsf@assigned-by-dhcp.cox.net>
2006/4/10, Junio C Hamano <junkio@cox.net>:
> "Franck Bui-Huu" <vagabon.xyz@gmail.com> writes:
>
> > It seems that "git commit -a -c ORIG_HEAD" command do not work as
> > expected.
> >
> > $ git commit -a -c ORIG_HEAD
> > $ git status
> > nothing to commit
> >
> > So it seems that c has been commmited this time...Is it the expected
> > behaviour ?
>
> You said "git commit -a" to tell it to commit all your changes
> in your working tree, using "-c ORIG_HEAD" which means "take the
> commit log message and authorship information from that commit".
>
> So I do not understand what else, other than both a and c
> getting committed (hence subsequent "git status" to report
> "nothing to commit'), you are expecting...
oops, I forgot that switch, sorry for the noise.
Thanks
--
Franck
^ permalink raw reply
* Re: [PATCH] git log [diff-tree options]...
From: Johannes Schindelin @ 2006-04-10 8:22 UTC (permalink / raw)
To: Junio C Hamano; +Cc: Linus Torvalds, git
In-Reply-To: <7vy7ye9uk8.fsf@assigned-by-dhcp.cox.net>
Hi,
On Sun, 9 Apr 2006, Junio C Hamano wrote:
> Johannes Schindelin <Johannes.Schindelin@gmx.de> writes:
>
> > Hi,
> >
> > On Sun, 9 Apr 2006, Johannes Schindelin wrote:
> >
> >> On Sun, 9 Apr 2006, Linus Torvalds wrote:
> >>
> >> > - keep it - for historical reasons - as a internal shorthand, and just
> >> > turn it into "git log --diff -cc"
> >>
> >> It is "git log --cc", right?
> >
> > Like this?
>
> I do not think so. You should default to --cc only there is no
> explicit command line stuff from the user.
Well, my idea was to get rid of the whatchanged script, and deprecate the
internal whatchanged. IMHO "git log" is much faster typed than "git
whatchanged", especially if you have no completion installed. I, for one,
will never ever again use whatchanged.
But you and the list gave me bad marks for that patch, and rightfully so.
Ciao,
Dscho
^ permalink raw reply
* Re: git commit broken ?
From: Junio C Hamano @ 2006-04-10 8:15 UTC (permalink / raw)
To: Franck Bui-Huu; +Cc: git
In-Reply-To: <cda58cb80604100102p92e5258qf33a128f75f1b088@mail.gmail.com>
"Franck Bui-Huu" <vagabon.xyz@gmail.com> writes:
> It seems that "git commit -a -c ORIG_HEAD" command do not work as
> expected.
>
> $ git commit -a -c ORIG_HEAD
> $ git status
> nothing to commit
>
> So it seems that c has been commmited this time...Is it the expected
> behaviour ?
You said "git commit -a" to tell it to commit all your changes
in your working tree, using "-c ORIG_HEAD" which means "take the
commit log message and authorship information from that commit".
So I do not understand what else, other than both a and c
getting committed (hence subsequent "git status" to report
"nothing to commit'), you are expecting...
^ permalink raw reply
* Re: [PATCH] git log [diff-tree options]...
From: Johannes Schindelin @ 2006-04-10 8:10 UTC (permalink / raw)
To: Timo Hirvonen; +Cc: git, junkio
In-Reply-To: <20060410012258.589f1581.tihirvon@gmail.com>
Hi,
On Mon, 10 Apr 2006, Timo Hirvonen wrote:
> Johannes Schindelin <Johannes.Schindelin@gmx.de> wrote:
>
> > +static int cmd_whatchanged(int argc, const char **argv, char **envp)
> > +{
> > + memmove(argv + 2, argv + 1, argc - 1);
>
> Shouldn't the size be sizeof(char *) * argc (NULL terminated array)?
> There's also overflow...
Yeah, this was some useless late-night coding. But you get the idea.
Ciao,
Dscho
^ permalink raw reply
* git commit broken ?
From: Franck Bui-Huu @ 2006-04-10 8:02 UTC (permalink / raw)
To: Git Mailing List
It seems that "git commit -a -c ORIG_HEAD" command do not work as
expected.
Here is an example:
$ ls
a b c
$ git status
nothing to commit
$ echo "good modif" > a
$ echo "temp modif" > c
$ git-update-index a
$ git commit -m "work in prog"
$ git reset --soft HEAD^
$ git status
#
# Updated but not checked in:
# (will commit)
#
# modified: a
#
#
# Changed but not updated:
# (use git-update-index to mark for commit)
#
# modified: c
#
$ git commit -a -c ORIG_HEAD
$ git status
nothing to commit
So it seems that c has been commmited this time...Is it the expected
behaviour ?
My git version:
$ git --version
git version 1.3.0.rc3.g0ed4
Thanks
--
Franck
^ permalink raw reply
* Re: git pull origin doesn't update the master
From: Junio C Hamano @ 2006-04-10 7:24 UTC (permalink / raw)
To: Aneesh Kumar; +Cc: git
In-Reply-To: <cc723f590604092345r7d0e2cedr8f9838d054ecb023@mail.gmail.com>
"Aneesh Kumar" <aneesh.kumar@gmail.com> writes:
> Work flow is now a bit complicated. I clone the repository. Now i need
> to edit remotes/origin to make sure what all branches i need to
> follow. And then do a git pull origin. Earlier i just need to do a
> clone and a git pull. I don't need to fast forward pu branch.
What you are saying is that the previous round did a wrong thing
without telling the user, and it just happened that you did not
care about the wrong thing it did.
It is a gentle reminder that heads that are rewound need to be
advertised as such. It is conceivable that in future versions
of git we might want to be able to mark some branches "this is
expected to be rewound" explicitly and make the clone operation
to take notice, to give you the plus sign automatically.
^ permalink raw reply
* Re: git pull origin doesn't update the master
From: Aneesh Kumar @ 2006-04-10 6:45 UTC (permalink / raw)
To: Junio C Hamano; +Cc: git
In-Reply-To: <7vr7469c4n.fsf@assigned-by-dhcp.cox.net>
On 4/10/06, Junio C Hamano <junkio@cox.net> wrote:
> "Aneesh Kumar" <aneesh.kumar@gmail.com> writes:
>
> > While updating the git code base the master branch is not getting
> > updated. First look tell me that the below commit is the issue
> > a9698bb22fb7b66e5882c3a5e7b2b8b53ea03f90
> >
> > git-pull.sh does
> > git-fetch --update-head-ok "$@" || exit 1
>
> Yes, this was done as an response to an explicit request from
> Andrew Morten.
>
> What Sean said about "pu" branch is correct.
>
>
Sean suggestion worked for me.
Work flow is now a bit complicated. I clone the repository. Now i need
to edit remotes/origin to make sure what all branches i need to
follow. And then do a git pull origin. Earlier i just need to do a
clone and a git pull. I don't need to fast forward pu branch. But then
i need to get the update of master branch. since git-fetch fails
update pu branch git pull origin fails to update master branch also
which i am really interested.
-aneesh
^ permalink raw reply
* Re: git pull origin doesn't update the master
From: Junio C Hamano @ 2006-04-10 6:29 UTC (permalink / raw)
To: Aneesh Kumar; +Cc: git
In-Reply-To: <cc723f590604092141q3517136cmc0a895a069021b8f@mail.gmail.com>
"Aneesh Kumar" <aneesh.kumar@gmail.com> writes:
> While updating the git code base the master branch is not getting
> updated. First look tell me that the below commit is the issue
> a9698bb22fb7b66e5882c3a5e7b2b8b53ea03f90
>
> git-pull.sh does
> git-fetch --update-head-ok "$@" || exit 1
Yes, this was done as an response to an explicit request from
Andrew Morten.
What Sean said about "pu" branch is correct.
^ permalink raw reply
* Re: [PATCH] Implement --fuzz= option for git-apply.
From: Eric W. Biederman @ 2006-04-10 5:52 UTC (permalink / raw)
To: Junio C Hamano; +Cc: git
In-Reply-To: <m1d5fqi23b.fsf@ebiederm.dsl.xmission.com>
ebiederm@xmission.com (Eric W. Biederman) writes:
> Currently to import the -mm tree I have to work around
> git-apply by using patch. Because some of Andrews
> patches in quilt will only apply with fuzz.
>
> Allow git-apply to handle fuzz makes it much easier to import
> the -mm tree into git. I am still only processing about 1.5 patch a
> second which for the 692 patches in 2.6.17-rc1-mm2 is still painful
> but it does help.
>
> If I just apply the patches and don't run git-mailinfo
> git-write-tree, and git-write-commit I get about 4 patches
> per second.
>
> This patch defaults to leaving fuzz processing off so if you don't
> want patches that only apply with fuzz you won't get them.
>
> If a patch does require fuzz to apply you will get a warning:
>> Fragment applied at offset: +-#lines (fuzz: #context_lines_deleted)
Bother I almost had it right the first time.
I forgot to remove the context lines from the new lines that we
apply, in addition to the old lines that we remove. This updated
patch fixes that problem.
Context lines patching themselves in is a weird bug.
Eric
diff --git a/apply.c b/apply.c
index 33b4271..4faf365 100644
--- a/apply.c
+++ b/apply.c
@@ -32,8 +32,9 @@ static int apply = 1;
static int no_add = 0;
static int show_index_info = 0;
static int line_termination = '\n';
+static int p_fuzz = 0;
static const char apply_usage[] =
-"git-apply [--stat] [--numstat] [--summary] [--check] [--index] [--apply] [--no-add] [--index-info] [--allow-binary-replacement] [-z] [-pNUM] [--whitespace=<nowarn|warn|error|error-all|strip>] <patch>...";
+"git-apply [--stat] [--numstat] [--summary] [--check] [--index] [--apply] [--no-add] [--index-info] [--allow-binary-replacement] [-z] [-pNUM] [--fuzz=NUM] [--whitespace=<nowarn|warn|error|error-all|strip>] <patch>...";
static enum whitespace_eol {
nowarn_whitespace,
@@ -100,6 +101,7 @@ static int max_change, max_len;
static int linenr = 1;
struct fragment {
+ unsigned long context;
unsigned long oldpos, oldlines;
unsigned long newpos, newlines;
const char *patch;
@@ -817,12 +819,15 @@ static int parse_fragment(char *line, un
int added, deleted;
int len = linelen(line, size), offset;
unsigned long oldlines, newlines;
+ unsigned long leading, trailing;
offset = parse_fragment_header(line, len, fragment);
if (offset < 0)
return -1;
oldlines = fragment->oldlines;
newlines = fragment->newlines;
+ leading = 0;
+ trailing = 0;
if (patch->is_new < 0) {
patch->is_new = !oldlines;
@@ -860,10 +865,14 @@ static int parse_fragment(char *line, un
case ' ':
oldlines--;
newlines--;
+ if (!deleted && !added)
+ leading++;
+ trailing++;
break;
case '-':
deleted++;
oldlines--;
+ trailing = 0;
break;
case '+':
/*
@@ -887,6 +896,7 @@ static int parse_fragment(char *line, un
}
added++;
newlines--;
+ trailing = 0;
break;
/* We allow "\ No newline at end of file". Depending
@@ -904,6 +914,10 @@ static int parse_fragment(char *line, un
}
if (oldlines || newlines)
return -1;
+ fragment->context = leading;
+ if (leading > trailing)
+ fragment->context = trailing;
+
/* If a fragment ends with an incomplete line, we failed to include
* it in the above loop because we hit oldlines == newlines == 0
* before seeing it.
@@ -1087,7 +1101,7 @@ static int read_old_data(struct stat *st
}
}
-static int find_offset(const char *buf, unsigned long size, const char *fragment, unsigned long fragsize, int line)
+static int find_offset(const char *buf, unsigned long size, const char *fragment, unsigned long fragsize, int line, int *lines)
{
int i;
unsigned long start, backwards, forwards;
@@ -1148,6 +1162,7 @@ static int find_offset(const char *buf,
n = (i >> 1)+1;
if (i & 1)
n = -n;
+ *lines = n;
return try;
}
@@ -1155,6 +1170,31 @@ static int find_offset(const char *buf,
* We should start searching forward and backward.
*/
return -1;
+}
+
+static void reduce_context(char **buf, int *size)
+{
+ char *ctx = *buf;
+ unsigned long ctxsize = *size;
+ unsigned long offset;
+
+ /* Remove the first line */
+ offset = 0;
+ while (offset <= ctxsize) {
+ if (ctx[offset++] == '\n')
+ break;
+ }
+ ctxsize -= offset;
+ ctx += offset;
+ /* Remove the last line */
+ offset = ctxsize - 1;
+ while (offset > 0) {
+ if (ctx[--offset] == '\n')
+ break;
+ }
+ ctxsize = offset + 1;
+ *buf = ctx;
+ *size = ctxsize;
}
struct buffer_desc {
@@ -1192,7 +1232,10 @@ static int apply_one_fragment(struct buf
int offset, size = frag->size;
char *old = xmalloc(size);
char *new = xmalloc(size);
+ char *oldlines, *newlines;
int oldsize = 0, newsize = 0;
+ int lines;
+ int fuzz, max_fuzz;
while (size > 0) {
int len = linelen(patch, size);
@@ -1241,23 +1284,42 @@ #ifdef NO_ACCURATE_DIFF
newsize--;
}
#endif
+
+ offset = -1; /* shutup gcc */
+ oldlines = old;
+ newlines = new;
+ lines = 0;
+ max_fuzz = (p_fuzz < frag->context) ? p_fuzz : frag->context;
+ for (fuzz = 0; fuzz <= max_fuzz; fuzz++) {
+ /* Reduce the number of context lines */
+ if (fuzz) {
+ reduce_context(&oldlines, &oldsize);
+ reduce_context(&newlines, &newsize);
+ }
- offset = find_offset(buf, desc->size, old, oldsize, frag->newpos);
- if (offset >= 0) {
- int diff = newsize - oldsize;
- unsigned long size = desc->size + diff;
- unsigned long alloc = desc->alloc;
-
- if (size > alloc) {
- alloc = size + 8192;
- desc->alloc = alloc;
- buf = xrealloc(buf, alloc);
- desc->buffer = buf;
+ offset = find_offset(buf, desc->size, oldlines, oldsize, frag->newpos + fuzz, &lines);
+ if (offset >= 0) {
+ int diff = newsize - oldsize;
+ unsigned long size = desc->size + diff;
+ unsigned long alloc = desc->alloc;
+
+ if (fuzz)
+ fprintf(stderr, "Fragment applied at offset: %d (fuzz: %d)\n",
+ lines, fuzz);
+
+ if (size > alloc) {
+ alloc = size + 8192;
+ desc->alloc = alloc;
+ buf = xrealloc(buf, alloc);
+ desc->buffer = buf;
+ }
+ desc->size = size;
+ memmove(buf + offset + newsize, buf + offset + oldsize, size - offset - newsize);
+ memcpy(buf + offset, newlines, newsize);
+ offset = 0;
+
+ break;
}
- desc->size = size;
- memmove(buf + offset + newsize, buf + offset + oldsize, size - offset - newsize);
- memcpy(buf + offset, new, newsize);
- offset = 0;
}
free(old);
@@ -1943,6 +2005,10 @@ int main(int argc, char **argv)
}
if (!strcmp(arg, "-z")) {
line_termination = 0;
+ continue;
+ }
+ if (!strncmp(arg, "--fuzz=", 7)) {
+ p_fuzz = atoi(arg + 7);
continue;
}
if (!strncmp(arg, "--whitespace=", 13)) {
^ permalink raw reply related
* Re: git pull origin doesn't update the master
From: sean @ 2006-04-10 5:03 UTC (permalink / raw)
To: Aneesh Kumar; +Cc: git, junkio
In-Reply-To: <cc723f590604092141q3517136cmc0a895a069021b8f@mail.gmail.com>
On Mon, 10 Apr 2006 10:11:05 +0530
"Aneesh Kumar" <aneesh.kumar@gmail.com> wrote:
> While updating the git code base the master branch is not getting
> updated. First look tell me that the below commit is the issue
> a9698bb22fb7b66e5882c3a5e7b2b8b53ea03f90
>
> git-pull.sh does
> git-fetch --update-head-ok "$@" || exit 1
>
> and git-fetch.sh exit with status 1 printing the below message
>
> * refs/heads/pu: does not fast forward to branch 'pu' of
> http://git.kernel.org/pub/scm/git/git;
> not updating.
>
The "pu" branch often won't fast forward because some commits have
been completely deleted in it since the last time you pulled.
If you want to track it, add a plus (+) sign to the proper line in
your .git/remotes/origin file, like this:
Pull: +refs/heads/pu:refs/heads/pu
Which tells git to deal with the problem for you by merging instead
of fast forwarding. Or you can just delete that line completely
if you don't want to track the pu branch at all.
HTH,
Sean
^ permalink raw reply
* Re: git pull origin doesn't update the master
From: Aneesh Kumar @ 2006-04-10 4:51 UTC (permalink / raw)
To: Git Mailing List, Junio C Hamano
In-Reply-To: <cc723f590604092141q3517136cmc0a895a069021b8f@mail.gmail.com>
On 4/10/06, Aneesh Kumar <aneesh.kumar@gmail.com> wrote:
> While updating the git code base the master branch is not getting
> updated. First look tell me that the below commit is the issue
> a9698bb22fb7b66e5882c3a5e7b2b8b53ea03f90
>
> git-pull.sh does
> git-fetch --update-head-ok "$@" || exit 1
>
> and git-fetch.sh exit with status 1 printing the below message
>
> * refs/heads/pu: does not fast forward to branch 'pu' of
> http://git.kernel.org/pub/scm/git/git;
> not updating.
>
>
I think the git-update-server-info is not run on kernel.org. I am
using the http fetch
562036a04223709de4922873238462007bcb529f refs/heads/pu
$ more pu
c52d221ba03c84e0b818d19f7ec30cb4d75fe509
$
-aneesh
^ permalink raw reply
* git pull origin doesn't update the master
From: Aneesh Kumar @ 2006-04-10 4:41 UTC (permalink / raw)
To: Git Mailing List, Junio C Hamano
While updating the git code base the master branch is not getting
updated. First look tell me that the below commit is the issue
a9698bb22fb7b66e5882c3a5e7b2b8b53ea03f90
git-pull.sh does
git-fetch --update-head-ok "$@" || exit 1
and git-fetch.sh exit with status 1 printing the below message
* refs/heads/pu: does not fast forward to branch 'pu' of
http://git.kernel.org/pub/scm/git/git;
not updating.
-aneesh
^ permalink raw reply
* Re: [RFH] Exploration of an alternative diff_delta() algorithm
From: Nicolas Pitre @ 2006-04-10 3:29 UTC (permalink / raw)
To: Peter Eriksen; +Cc: git
In-Reply-To: <20060409224548.GB21455@erlang.gbar.dtu.dk>
[-- Attachment #1: Type: TEXT/PLAIN, Size: 1001 bytes --]
On Mon, 10 Apr 2006, Peter Eriksen wrote:
> On Sun, Apr 09, 2006 at 01:45:00PM -0400, Nicolas Pitre wrote:
> ...
> > Try this with the README file from the git source tree:
> >
> > sed s/git/GIT/g < ./README > /tmp/README.mod
> > test-delta -d ./README /tmp/README.mod /tmp/README.delta
> > [BOOM!]
>
> I found the bug. The code still has some limitations, but now
> it passes the test suite. Thanks for your help, Nicolas.
OK here's some more meat for you:
Copy the same README file from the git source tree, then edit the copied
version so the "Blob Object" section and the "Tree Object" section are
swapped around like shown in the attached patch.
The best delta that can be achieved is 24 bytes.
With the current code the produced delta is 42 bytes.
With your code the resulting delta is 4978 bytes, about twice as large
as the attached patch.
One major limitation of your algorithm appears to not have a global view
of the base buffer before starting to find matches.
Nicolas
[-- Attachment #2: Type: TEXT/PLAIN, Size: 2372 bytes --]
--- f1 2006-04-09 13:31:26.000000000 -0400
+++ f2 2006-04-09 23:04:10.000000000 -0400
@@ -87,26 +87,6 @@
The object types in some more detail:
-Blob Object
-~~~~~~~~~~~
-A "blob" object is nothing but a binary blob of data, and doesn't
-refer to anything else. There is no signature or any other
-verification of the data, so while the object is consistent (it 'is'
-indexed by its sha1 hash, so the data itself is certainly correct), it
-has absolutely no other attributes. No name associations, no
-permissions. It is purely a blob of data (i.e. normally "file
-contents").
-
-In particular, since the blob is entirely defined by its data, if two
-files in a directory tree (or in multiple different versions of the
-repository) have the same contents, they will share the same blob
-object. The object is totally independent of its location in the
-directory tree, and renaming a file does not change the object that
-file is associated with in any way.
-
-A blob is typically created when gitlink:git-update-index[1]
-is run, and its data can be accessed by gitlink:git-cat-file[1].
-
Tree Object
~~~~~~~~~~~
The next hierarchical object type is the "tree" object. A tree object
@@ -147,6 +127,26 @@
its data can be accessed by gitlink:git-ls-tree[1].
Two trees can be compared with gitlink:git-diff-tree[1].
+Blob Object
+~~~~~~~~~~~
+A "blob" object is nothing but a binary blob of data, and doesn't
+refer to anything else. There is no signature or any other
+verification of the data, so while the object is consistent (it 'is'
+indexed by its sha1 hash, so the data itself is certainly correct), it
+has absolutely no other attributes. No name associations, no
+permissions. It is purely a blob of data (i.e. normally "file
+contents").
+
+In particular, since the blob is entirely defined by its data, if two
+files in a directory tree (or in multiple different versions of the
+repository) have the same contents, they will share the same blob
+object. The object is totally independent of its location in the
+directory tree, and renaming a file does not change the object that
+file is associated with in any way.
+
+A blob is typically created when gitlink:git-update-index[1]
+is run, and its data can be accessed by gitlink:git-cat-file[1].
+
Commit Object
~~~~~~~~~~~~~
The "commit" object is an object that introduces the notion of
^ 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