* Bad error message
From: Robin Rosenberg (list subscriber) @ 2006-05-04 23:57 UTC (permalink / raw)
To: git
Hi,
While playing with git I got the following "impossible" error message:
$ git commit --amend
fatal: Ref HEAD is at 3cec3036287d6b24f7ad7f724f8bb9d4032fb1a3 but expected
3cec3036287d6b24f7ad7f724f8bb9d4032fb1a3
Since impossible things happen rarely, I was somewhat puzzled and it turned
out not to be so impossible after all, but a rather typical C bug. Since I
fixed my working directory using git-reset, I'm not sure how to verify the
code (suggestions welcome), but I'm not sure if that's important since the
code being replaced by this patch probably wasn't tested either. :/
Maybe someone could explain what might have been wrong with my work space (git
status turned up nothing wrong or missing).
-- robin
--- git-1.3.1.orig/update-ref.c 2006-04-25 08:07:54.000000000 +0200
+++ git-1.3.1/update-ref.c 2006-05-04 16:30:04.000000000 +0200
@@ -43,8 +43,13 @@
die("No such ref: %s", refname);
if (oldval) {
- if (memcmp(currsha1, oldsha1, 20))
- die("Ref %s is at %s but expected %s", refname, sha1_to_hex(currsha1), sha1_to_hex(oldsha1));
+ if (memcmp(currsha1, oldsha1, 20)) {
+ char sha1str1[41];
+ char sha1str2[41];
+ strcpy(sha1str1, sha1_to_hex(currsha1));
+ strcpy(sha1str2, sha1_to_hex(oldsha1));
+ die("Ref %s is at %s but expected %s", refname, sha1str1, sha1str2);
+ }
/* Nothing to do? */
if (!memcmp(oldsha1, sha1, 20))
exit(0);
^ permalink raw reply
* Re: [PATCH] Teach fmt-patch to write individual files.
From: Junio C Hamano @ 2006-05-05 0:09 UTC (permalink / raw)
To: Johannes Schindelin; +Cc: git
In-Reply-To: <Pine.LNX.4.63.0605050115440.12795@wbgn013.biozentrum.uni-wuerzburg.de>
Johannes Schindelin <Johannes.Schindelin@gmx.de> writes:
> When called with "--stdout", it still writes to standard output.
>
> Notable differences to git-format-patch:
>
> - since fmt-patch uses the standardized logging machinery, it is
> no longer "From nobody", but "From <commit_sha1>",
Yes, and the date on that UNIX-From line has been updated ;-).
> - the empty lines before and after the "---" just before the
> diffstat are no longer there,
Personally, I find this the most annoying myself. I am not
complaining to you because as you know you inherited this
behaviour from my code.
> - git-format-patch outputs the commit_sha1 just before the first
> diff, which fmt-patch does not,
Which should be fine.
> - the file names are no longer output to stdout, but to stderr
> (since stdout is freopen()ed all the time), and
Which might be a bigger deal; I suspect people capture that while
dumping patches into individual files, and do their
postprocessing using the list of filenames.
> - "git fmt-patch HEAD^" does not work as expected: it outputs
> *all* commits reachable from HEAD^!
If we really wanted to handle this, you could do something like
what builtin-diff does before letting the revision machinery
start walking the revision tree. Look at pending objects, and
if you find only one UNINTERESTING commit, add_object the
current HEAD there as well. Personally I do not think it is
worth it; rather we would probably want to standardize on rev-list
syntax.
Two major differences you forgot to mention.
One is that it does not do the "git cherry" filtering. It is
not a big deal for me personally, but some people may be
depending on it. I dunno.
Another is -o outdir, which should be trivial to add once you
have implemented output switching with freopen().
Anyhow, thanks for starting this.
^ permalink raw reply
* Re: Bad error message
From: Junio C Hamano @ 2006-05-05 0:20 UTC (permalink / raw)
To: Robin Rosenberg (list subscriber); +Cc: git
In-Reply-To: <200605041957.26194.robin.rosenberg.lists@dewire.com>
"Robin Rosenberg (list subscriber)" <robin.rosenberg.lists@dewire.com> writes:
> @@ -43,8 +43,13 @@
> die("No such ref: %s", refname);
>
> if (oldval) {
> - if (memcmp(currsha1, oldsha1, 20))
> - die("Ref %s is at %s but expected %s", refname, sha1_to_hex(currsha1), sha1_to_hex(oldsha1));
> + if (memcmp(currsha1, oldsha1, 20)) {
> + char sha1str1[41];
> + char sha1str2[41];
> + strcpy(sha1str1, sha1_to_hex(currsha1));
> + strcpy(sha1str2, sha1_to_hex(oldsha1));
> + die("Ref %s is at %s but expected %s", refname, sha1str1, sha1str2);
> + }
Your patch looks correct, but probably is made unnecessary with
the "you can use up to 4 sha1_to_hex() safely" patch Linus did.
We have it in "master" and my plan is to cherry-pick it to
"maint" branch and included it in the next stale release 1.3.3,
along with core.prefersymlinkrefs patch also only in "master",
if we do not hear somebody scream in the next few days.
^ permalink raw reply
* Re: Unresolved issues #2 (shallow clone again)
From: Junio C Hamano @ 2006-05-05 0:25 UTC (permalink / raw)
To: Carl Worth; +Cc: git
In-Reply-To: <87mzdx7mh9.wl%cworth@cworth.org>
Carl Worth <cworth@cworth.org> writes:
> ... So the conversation changes from "I WANT
> <fetch-heads> and I HAVE <heads>" to one of "I WANT <fetch-heads>, and
> I HAVE <heads>, except that I'm MISSING <cauterized-commits>".
>
> Finally, whenever a fetch receives an commit object that is in its
> list of cauterized commits, it should remove that commit from the
> list. This allows a shallow clone to be naturally migrated to
> something unshallow. And the user can do this as incrementally as
> desired based on the need to see more history:
>
> get a bit:
> git fetch somewhere --since=2.weeks.ago
>
> then a bit more:
> git fetch somewhere --since=1.year.ago
>
> then get it all:
> git fetch somewhere
>
> Maybe that's no different from Junio's original proposal. If not, what
> do you see in the above that wouldn't work?
Lack of actual code to do all that ;-)
Jokes aside, I think listing the updated conversation elements
like you did above is a good step forward.
The vocabulary we would want from the requestor side is probably
(at least):
I WANT to have these
I HAVE these
I'm MISSING these
Don't bother with these this time around (--since, ^v2.6.16, ...)
I am not sure how we would want to encode the last one and have
it used by rev-list on the upload-pack end safely and sanely.
And the responder side needs to be able to say, "Now you are
MISSING these, remember it and tell me you are missing them next
time you make a request". That would be, in the simplest case,
a list of commit IDs to cauterize, but I am not sure what is the
right way to come up with that list. Especially I do not know
if --boundary would/should work with --objects.
^ permalink raw reply
* Re: [PATCH] Teach fmt-patch to write individual files.
From: Johannes Schindelin @ 2006-05-05 0:56 UTC (permalink / raw)
To: Junio C Hamano; +Cc: git
In-Reply-To: <7vhd452uzn.fsf@assigned-by-dhcp.cox.net>
Hi,
On Thu, 4 May 2006, Junio C Hamano wrote:
> Johannes Schindelin <Johannes.Schindelin@gmx.de> writes:
>
> > When called with "--stdout", it still writes to standard output.
> >
> > Notable differences to git-format-patch:
> >
> > - since fmt-patch uses the standardized logging machinery, it is
> > no longer "From nobody", but "From <commit_sha1>",
>
> Yes, and the date on that UNIX-From line has been updated ;-).
Right.
> > - the empty lines before and after the "---" just before the
> > diffstat are no longer there,
>
> Personally, I find this the most annoying myself. I am not
> complaining to you because as you know you inherited this
> behaviour from my code.
How about this?
-- snip --
diff --git a/log-tree.c b/log-tree.c
index d92abaf..6379d43 100644
--- a/log-tree.c
+++ b/log-tree.c
@@ -86,7 +86,7 @@ int log_tree_diff_flush(struct rev_info
}
if (opt->loginfo && !opt->no_commit_id)
- show_log(opt, opt->loginfo, opt->diffopt.with_stat ? "---\n" : "\n");
+ show_log(opt, opt->loginfo, opt->diffopt.with_stat ? "\n---\n\n" : "\n");
diff_flush(&opt->diffopt);
return 1;
}
-- snap --
> > - git-format-patch outputs the commit_sha1 just before the first
> > diff, which fmt-patch does not,
>
> Which should be fine.
Yeah, I just wanted to mention it in case people rely on it.
> > - the file names are no longer output to stdout, but to stderr
> > (since stdout is freopen()ed all the time), and
>
> Which might be a bigger deal; I suspect people capture that while
> dumping patches into individual files, and do their
> postprocessing using the list of filenames.
I hoped it is not necessary to "FILE *realstdout = fdopen(dup(1));" but I
can do it if this is wanted.
> > - "git fmt-patch HEAD^" does not work as expected: it outputs
> > *all* commits reachable from HEAD^!
>
> If we really wanted to handle this, you could do something like
> what builtin-diff does before letting the revision machinery
> start walking the revision tree. Look at pending objects, and
> if you find only one UNINTERESTING commit, add_object the
> current HEAD there as well. Personally I do not think it is
> worth it; rather we would probably want to standardize on rev-list
> syntax.
Well, I have to get used to add ".." after HEAD^, but that is probably not
very difficult. I would like fmt-patch to error out without a range,
though.
> Two major differences you forgot to mention.
>
> One is that it does not do the "git cherry" filtering. It is
> not a big deal for me personally, but some people may be
> depending on it. I dunno.
Oops. I really did not think of that.
> Another is -o outdir, which should be trivial to add once you
> have implemented output switching with freopen().
Yes, this becomes easy now. I'll do that next.
Ciao,
Dscho
^ permalink raw reply related
* Re: [ANNOUNCE] Git wiki
From: linux @ 2006-05-05 0:56 UTC (permalink / raw)
To: git; +Cc: linux
Actually, AFAICT from looking at the mailing list history, it's not dirty
politics: the tie-breaker was the support and enthusiasm of the mercurial
developers. It passed with only minor comment on the git mailing list,
but it was a Big Thing to the hg folks.
There are ups and downs. OpenSolaris is definitely the big fish in
the mercurial pond (that wasn't *meant* to sound like a recipe for
heavy metal toxicity), and will get lots of attention, but git has more
real-world experience. The big fish in the git pond is Linus and Linux.
In any case, mercurial and git are really very similar, far closer
to each other than any third system, so it's not like the decision is
a descent into heresy. Hopefully some useful cross-pollination
can occur, and converting history from one to the other would be
simple if anyone ever wanted to.
As for explicit renames, people are confused on the subject.
IMHO, the two most revolutionary things about git are:
- Finally, a complete break from file-oriented history. History is made
of trees, and trees are made of files. There is no direct connection
between files in different commits.
- An explicit representation of an in-progress merge.
This is what makes multiple merge strategies easily implementable.
Third, I suppose, is the raw diff format and the diffcore pipeline.
But finally getting away from the SCCS & RCS idea that the file is the
unit of history is one of git's Great Features, and it shouldn't be
thrown away.
What people who are asking for explicit rename tracking actually want
is automatic rename merging. If branch A renames a file, and branch B
corrects a typo on a comment somewhere, they'd like the merge to
both patch and rename the file. If you can do that, you have met the
need, even if your solution isn't the one the feature requester
imagined.
(This is the general consulting problem: a client calls when they've
been trying a solution and can't get past some problem. Usually, this
is because they've wandered into a blind alley, and what they're asking
for is either far more difficult than necessary, or will just lead them
into greater problems. The first thing you have to determine is what
they actually want to do, as distinct from how they've decided to do it.)
But, as Linus has pointed out, this is a very partial solution which
introduces a lot of difficulties elsewhere. File renaming is a subset of
the general class of code reorganizations. Source files will be split,
merged, and have functions moved back and forth. You want the patch to
find the code it applies to even if that code was moved.
And that can be done by taking a more global view of the patch.
Identical file names is only a heuristic. If the hunk on branch A
can't find a place to apply on the same file in branch B, then
you have to look a little harder, either at changes from branch B
that introduce matching code elsewhere, or perhaps looking
through history for a change that removed the match from the
obvious place to see if it added a match elsewhere.
The one thing that makes this difficult is git-read-tree's automatic
collapse of "trivial" merges. If branch B moves foo() unchanged from
x.c to y.c, while branch A doesn't touch y.c, but edits foo() in x.c,
git-read-tree will collapse the changes to y.c before even invoking
the advanced resolve script.
(The solution might be to keep *four* versions of the file in the index:
the three pre-merge, *and* the post-merge. Then git-write-tree makes
sure everything has a stage 0 entry and strips out the stage 1, 2 and
3 entries. This way, one merge algorithm can use another as a
subroutine but decide not to accept something it did.)
But anyway, it's the merging that's the desired feature. Explicitly
recording renames is only the means to that end, and is superfluous
if there's another way of getting there. (And the place to look for
interesting new ideas in that area Darcs.)
^ permalink raw reply
* [PATCH] fmt-patch: output file names to stdout
From: Johannes Schindelin @ 2006-05-05 1:33 UTC (permalink / raw)
To: git, junkio
Signed-off-by: Johannes Schindelin <Johannes.Schindelin@gmx.de>
---
builtin-log.c | 7 ++++++-
1 files changed, 6 insertions(+), 1 deletions(-)
diff --git a/builtin-log.c b/builtin-log.c
index 576703c..1649f49 100644
--- a/builtin-log.c
+++ b/builtin-log.c
@@ -75,6 +75,8 @@ static int istitlechar(char c)
(c >= '0' && c <= '9') || c == '.' || c == '_';
}
+static FILE *realstdout = NULL;
+
static void reopen_stdout(struct commit *commit, int nr)
{
char filename[1024];
@@ -117,7 +119,7 @@ static void reopen_stdout(struct commit
len--;
}
strcpy(filename + len, ".txt");
- fprintf(stderr, "%s\n", filename);
+ fprintf(realstdout, "%s\n", filename);
freopen(filename, "w", stdout);
}
@@ -149,6 +151,9 @@ int cmd_format_patch(int argc, const cha
argv++;
}
+ if (!use_stdout)
+ realstdout = fdopen(dup(1), "w");
+
prepare_revision_walk(&rev);
while ((commit = get_revision(&rev)) != NULL) {
/* ignore merges */
--
1.3.1.g6d0e-dirty
^ permalink raw reply related
* [PATCH] fmt-patch: implement -o <dir>
From: Johannes Schindelin @ 2006-05-05 1:33 UTC (permalink / raw)
To: git, junkio
I had to move the command line parsing around a little; setup_revisions()
could mistaken <dir> for a valid ref.
Signed-off-by: Johannes Schindelin <Johannes.Schindelin@gmx.de>
---
builtin-log.c | 44 ++++++++++++++++++++++++++++++++++----------
1 files changed, 34 insertions(+), 10 deletions(-)
diff --git a/builtin-log.c b/builtin-log.c
index 1649f49..53a47c9 100644
--- a/builtin-log.c
+++ b/builtin-log.c
@@ -76,15 +76,22 @@ static int istitlechar(char c)
}
static FILE *realstdout = NULL;
+static char *output_directory = NULL;
static void reopen_stdout(struct commit *commit, int nr)
{
char filename[1024];
char *sol;
- int len;
+ int len = 0;
+ if (output_directory) {
+ strncpy(filename, output_directory, 1010);
+ len = strlen(filename);
+ if (filename[len - 1] != '/')
+ filename[len++] = '/';
+ }
- sprintf(filename, "%04d", nr);
+ sprintf(filename + len, "%04d", nr);
len = strlen(filename);
sol = strstr(commit->buffer, "\n\n");
@@ -128,7 +135,7 @@ int cmd_format_patch(int argc, const cha
struct commit *commit;
struct commit **list = NULL;
struct rev_info rev;
- int nr = 0, total;
+ int nr = 0, total, i, j;
int use_stdout = 0;
init_revisions(&rev);
@@ -140,16 +147,31 @@ int cmd_format_patch(int argc, const cha
rev.combine_merges = 0;
rev.ignore_merges = 1;
rev.diffopt.output_format = DIFF_FORMAT_PATCH;
- argc = setup_revisions(argc, argv, &rev, "HEAD");
- while (argc > 1) {
- if (!strcmp(argv[1], "--stdout"))
+ /*
+ * Parse the arguments before setup_revisions(), or something
+ * like "git fmt-patch -o a123 HEAD^.." may fail; a123 is
+ * possibly a valid SHA1.
+ */
+ for (i = 1, j = 1; i < argc; i++) {
+ if (!strcmp(argv[i], "--stdout"))
use_stdout = 1;
- else
- die ("unrecognized argument: %s", argv[1]);
- argc--;
- argv++;
+ else if (!strcmp(argv[i], "-o")) {
+ if (argc < 3)
+ die ("Which directory?");
+ if (mkdir(argv[i + 1], 0777) < 0 && errno != EEXIST)
+ die("Could not create directory %s",
+ argv[i + 1]);
+ output_directory = strdup(argv[i + 1]);
+ i++;
+ } else
+ argv[j++] = argv[i];
}
+ argc = j;
+
+ argc = setup_revisions(argc, argv, &rev, "HEAD");
+ if (argc > 1)
+ die ("unrecognized argument: %s", argv[1]);
if (!use_stdout)
realstdout = fdopen(dup(1), "w");
@@ -177,6 +199,8 @@ int cmd_format_patch(int argc, const cha
if (!use_stdout)
fclose(stdout);
}
+ if (output_directory)
+ free(output_directory);
free(list);
return 0;
}
--
1.3.1.g6d0e-dirty
^ permalink raw reply related
* [PATCH] Teach fmt-patch about --numbered
From: Johannes Schindelin @ 2006-05-05 2:30 UTC (permalink / raw)
To: git, junkio
Signed-off-by: Johannes Schindelin <Johannes.Schindelin@gmx.de>
---
builtin-log.c | 9 ++++++++-
commit.c | 5 +----
commit.h | 2 +-
log-tree.c | 15 ++++++++++++---
rev-list.c | 2 +-
revision.h | 1 +
show-branch.c | 2 +-
7 files changed, 25 insertions(+), 11 deletions(-)
diff --git a/builtin-log.c b/builtin-log.c
index 53a47c9..43c7ecd 100644
--- a/builtin-log.c
+++ b/builtin-log.c
@@ -137,6 +137,7 @@ int cmd_format_patch(int argc, const cha
struct rev_info rev;
int nr = 0, total, i, j;
int use_stdout = 0;
+ int numbered = 0;
init_revisions(&rev);
rev.commit_format = CMIT_FMT_EMAIL;
@@ -156,6 +157,9 @@ int cmd_format_patch(int argc, const cha
for (i = 1, j = 1; i < argc; i++) {
if (!strcmp(argv[i], "--stdout"))
use_stdout = 1;
+ else if (!strcmp(argv[i], "-n") ||
+ !strcmp(argv[i], "--numbered"))
+ numbered = 1;
else if (!strcmp(argv[i], "-o")) {
if (argc < 3)
die ("Which directory?");
@@ -186,11 +190,14 @@ int cmd_format_patch(int argc, const cha
list[nr - 1] = commit;
}
total = nr;
+ if (numbered)
+ rev.total = total;
while (0 <= --nr) {
int shown;
commit = list[nr];
+ rev.nr = total - nr;
if (!use_stdout)
- reopen_stdout(commit, total - nr);
+ reopen_stdout(commit, rev.nr);
shown = log_tree_commit(&rev, commit);
free(commit->buffer);
commit->buffer = NULL;
diff --git a/commit.c b/commit.c
index 42b44bb..93b3903 100644
--- a/commit.c
+++ b/commit.c
@@ -489,17 +489,14 @@ static int add_merge_info(enum cmit_fmt
return offset;
}
-unsigned long pretty_print_commit(enum cmit_fmt fmt, const struct commit *commit, unsigned long len, char *buf, unsigned long space, int abbrev)
+unsigned long pretty_print_commit(enum cmit_fmt fmt, const struct commit *commit, unsigned long len, char *buf, unsigned long space, int abbrev, const char *subject)
{
int hdr = 1, body = 0;
unsigned long offset = 0;
int indent = 4;
int parents_shown = 0;
const char *msg = commit->buffer;
- const char *subject = NULL;
- if (fmt == CMIT_FMT_EMAIL)
- subject = "Subject: [PATCH] ";
if (fmt == CMIT_FMT_ONELINE || fmt == CMIT_FMT_EMAIL)
indent = 0;
diff --git a/commit.h b/commit.h
index 01eec60..8d7514c 100644
--- a/commit.h
+++ b/commit.h
@@ -51,7 +51,7 @@ enum cmit_fmt {
};
extern enum cmit_fmt get_commit_format(const char *arg);
-extern unsigned long pretty_print_commit(enum cmit_fmt fmt, const struct commit *, unsigned long len, char *buf, unsigned long space, int abbrev);
+extern unsigned long pretty_print_commit(enum cmit_fmt fmt, const struct commit *, unsigned long len, char *buf, unsigned long space, int abbrev, const char *subject);
/** Removes the first commit from a list sorted by date, and adds all
* of its parents.
diff --git a/log-tree.c b/log-tree.c
index d92abaf..cec7068 100644
--- a/log-tree.c
+++ b/log-tree.c
@@ -20,6 +20,7 @@ void show_log(struct rev_info *opt, stru
int abbrev_commit = opt->abbrev_commit ? opt->abbrev : 40;
const char *extra;
int len;
+ char* subject = NULL;
opt->loginfo = NULL;
if (!opt->verbose_header) {
@@ -50,10 +51,18 @@ void show_log(struct rev_info *opt, stru
* Print header line of header..
*/
- if (opt->commit_format == CMIT_FMT_EMAIL)
+ if (opt->commit_format == CMIT_FMT_EMAIL) {
+ if (opt->total > 0) {
+ static char buffer[64];
+ snprintf(buffer, sizeof(buffer),
+ "Subject: [PATCH %d/%d] ",
+ opt->nr, opt->total);
+ subject = buffer;
+ } else
+ subject = "Subject: [PATCH] ";
printf("From %s Thu Apr 7 15:13:13 2005\n",
sha1_to_hex(commit->object.sha1));
- else {
+ } else {
printf("%s%s",
opt->commit_format == CMIT_FMT_ONELINE ? "" : "commit ",
diff_unique_abbrev(commit->object.sha1, abbrev_commit));
@@ -69,7 +78,7 @@ void show_log(struct rev_info *opt, stru
/*
* And then the pretty-printed message itself
*/
- len = pretty_print_commit(opt->commit_format, commit, ~0u, this_header, sizeof(this_header), abbrev);
+ len = pretty_print_commit(opt->commit_format, commit, ~0u, this_header, sizeof(this_header), abbrev, subject);
printf("%s%s%s", this_header, extra, sep);
}
diff --git a/rev-list.c b/rev-list.c
index 89b3343..347f627 100644
--- a/rev-list.c
+++ b/rev-list.c
@@ -83,7 +83,7 @@ static void show_commit(struct commit *c
static char pretty_header[16384];
pretty_print_commit(revs.commit_format, commit, ~0,
pretty_header, sizeof(pretty_header),
- revs.abbrev);
+ revs.abbrev, NULL);
printf("%s%c", pretty_header, hdr_termination);
}
fflush(stdout);
diff --git a/revision.h b/revision.h
index 48d7b4c..62759f7 100644
--- a/revision.h
+++ b/revision.h
@@ -58,6 +58,7 @@ struct rev_info {
unsigned int abbrev;
enum cmit_fmt commit_format;
struct log_info *loginfo;
+ int nr, total;
/* special limits */
int max_count;
diff --git a/show-branch.c b/show-branch.c
index 268c57b..bbe26c2 100644
--- a/show-branch.c
+++ b/show-branch.c
@@ -259,7 +259,7 @@ static void show_one_commit(struct commi
struct commit_name *name = commit->object.util;
if (commit->object.parsed)
pretty_print_commit(CMIT_FMT_ONELINE, commit, ~0,
- pretty, sizeof(pretty), 0);
+ pretty, sizeof(pretty), 0, NULL);
else
strcpy(pretty, "(unavailable)");
if (!strncmp(pretty, "[PATCH] ", 8))
--
1.3.1.g5f039
^ permalink raw reply related
* [PATCH] Teach fmt-patch about --keep-subject
From: Johannes Schindelin @ 2006-05-05 2:31 UTC (permalink / raw)
To: git, junkio
Signed-off-by: Johannes Schindelin <Johannes.Schindelin@gmx.de>
---
builtin-log.c | 16 ++++++++++++----
log-tree.c | 5 ++++-
2 files changed, 16 insertions(+), 5 deletions(-)
diff --git a/builtin-log.c b/builtin-log.c
index 43c7ecd..0027998 100644
--- a/builtin-log.c
+++ b/builtin-log.c
@@ -78,7 +78,7 @@ static int istitlechar(char c)
static FILE *realstdout = NULL;
static char *output_directory = NULL;
-static void reopen_stdout(struct commit *commit, int nr)
+static void reopen_stdout(struct commit *commit, int nr, int keep_subject)
{
char filename[1024];
char *sol;
@@ -100,7 +100,7 @@ static void reopen_stdout(struct commit
sol += 2;
/* strip [PATCH] or [PATCH blabla] */
- if (!strncmp(sol, "[PATCH", 6)) {
+ if (!keep_subject && !strncmp(sol, "[PATCH", 6)) {
char *eos = strchr(sol + 6, ']');
if (eos) {
while (isspace(*eos))
@@ -138,6 +138,7 @@ int cmd_format_patch(int argc, const cha
int nr = 0, total, i, j;
int use_stdout = 0;
int numbered = 0;
+ int keep_subject = 0;
init_revisions(&rev);
rev.commit_format = CMIT_FMT_EMAIL;
@@ -160,7 +161,11 @@ int cmd_format_patch(int argc, const cha
else if (!strcmp(argv[i], "-n") ||
!strcmp(argv[i], "--numbered"))
numbered = 1;
- else if (!strcmp(argv[i], "-o")) {
+ else if (!strcmp(argv[i], "-k") ||
+ !strcmp(argv[i], "--keep-subject")) {
+ keep_subject = 1;
+ rev.total = -1;
+ } else if (!strcmp(argv[i], "-o")) {
if (argc < 3)
die ("Which directory?");
if (mkdir(argv[i + 1], 0777) < 0 && errno != EEXIST)
@@ -173,6 +178,9 @@ int cmd_format_patch(int argc, const cha
}
argc = j;
+ if (numbered && keep_subject < 0)
+ die ("-n and -k are mutually exclusive.");
+
argc = setup_revisions(argc, argv, &rev, "HEAD");
if (argc > 1)
die ("unrecognized argument: %s", argv[1]);
@@ -197,7 +205,7 @@ int cmd_format_patch(int argc, const cha
commit = list[nr];
rev.nr = total - nr;
if (!use_stdout)
- reopen_stdout(commit, rev.nr);
+ reopen_stdout(commit, rev.nr, keep_subject);
shown = log_tree_commit(&rev, commit);
free(commit->buffer);
commit->buffer = NULL;
diff --git a/log-tree.c b/log-tree.c
index cec7068..526d578 100644
--- a/log-tree.c
+++ b/log-tree.c
@@ -58,8 +58,11 @@ void show_log(struct rev_info *opt, stru
"Subject: [PATCH %d/%d] ",
opt->nr, opt->total);
subject = buffer;
- } else
+ } else if (opt->total == 0)
subject = "Subject: [PATCH] ";
+ else
+ subject = "Subject: ";
+
printf("From %s Thu Apr 7 15:13:13 2005\n",
sha1_to_hex(commit->object.sha1));
} else {
--
1.3.1.g5f039
^ permalink raw reply related
* Re: [PATCH] binary patch.
From: Nicolas Pitre @ 2006-05-05 2:47 UTC (permalink / raw)
To: Junio C Hamano; +Cc: git
In-Reply-To: <7vodyd2vqn.fsf@assigned-by-dhcp.cox.net>
On Thu, 4 May 2006, Junio C Hamano wrote:
> This adds "binary patch" to the diff output and teaches apply
> what to do with them.
This is nice.
However I'd deflate the delta data before encoding it with base85.
Nicolas
^ permalink raw reply
* Re: Unresolved issues #2 (shallow clone again)
From: Martin Langhoff @ 2006-05-05 5:17 UTC (permalink / raw)
To: Junio C Hamano; +Cc: Carl Worth, git
In-Reply-To: <7v1wv92u7o.fsf@assigned-by-dhcp.cox.net>
On 5/5/06, Junio C Hamano <junkio@cox.net> wrote:
> The vocabulary we would want from the requestor side is probably
> (at least):
>
> I WANT to have these
> I HAVE these
> I'm MISSING these
> Don't bother with these this time around (--since, ^v2.6.16, ...)
Thinking... does the MISSING part matter at all? It seems that what
really matters are the "ignore rules". The pull may bring in a new
merge of a long-running branch, whose mergebase falls out of the
ignore rules.
In that case, the server should apply the ignore rules. Except that
later merges in the local repo would perhaps have to deal with missing
part of the history. I suspect it should refuse to merge something we
don't have all the merging parts for.
cheers,
martin
^ permalink raw reply
* Re: Unresolved issues #2 (shallow clone again)
From: Carl Worth @ 2006-05-05 5:23 UTC (permalink / raw)
To: Martin Langhoff; +Cc: Junio C Hamano, git
In-Reply-To: <46a038f90605042217n3261b14cxd63f35a31223848e@mail.gmail.com>
[-- Attachment #1: Type: text/plain, Size: 1119 bytes --]
On Fri, 5 May 2006 17:17:10 +1200, "Martin Langhoff" wrote:
> > I WANT to have these
> > I HAVE these
> > I'm MISSING these
> > Don't bother with these this time around (--since, ^v2.6.16, ...)
>
> Thinking... does the MISSING part matter at all?
Yes.
Imagine doing a shallow clone and then fetching a tree that includes a
blob that existed before MISSING. If we say HAVE without MISSING then
the server will not send that blob and we'll be left with a broken
tree.
> In that case, the server should apply the ignore rules. Except that
> later merges in the local repo would perhaps have to deal with missing
> part of the history. I suspect it should refuse to merge something we
> don't have all the merging parts for.
Yeah, shallow clones can shake up the conventions a bit. It's
definitely common for a repository to only have a single parent-less
commit, such that there is always an identifiable merge base for any
pair of revisions. Shallow clones would make (effectively) parent-less
commits much more common.
Should be fun to see what things fall over with this...
-Carl
[-- Attachment #2: Type: application/pgp-signature, Size: 189 bytes --]
^ permalink raw reply
* Re: Unresolved issues #2 (shallow clone again)
From: Jakub Narebski @ 2006-05-05 5:48 UTC (permalink / raw)
To: git
In-Reply-To: <87bqud6o4p.wl%cworth@cworth.org>
Carl Worth wrote:
> On Fri, 5 May 2006 17:17:10 +1200, "Martin Langhoff" wrote:
>> In that case, the server should apply the ignore rules. Except that
>> later merges in the local repo would perhaps have to deal with missing
>> part of the history. I suspect it should refuse to merge something we
>> don't have all the merging parts for.
>
> Yeah, shallow clones can shake up the conventions a bit. It's
> definitely common for a repository to only have a single parent-less
> commit, such that there is always an identifiable merge base for any
> pair of revisions. Shallow clones would make (effectively) parent-less
> commits much more common.
I wonder if it would be possible for git to:
a) as for a fetch which would bring all the commits up to the merge base
(and merge base has to be calculated on the server side I think),
i.e. give command to use (for fetch or for force baseless merge)
b) fetch the commits
c) do merge
d) optionally re-cauterize history again
--
Jakub Narebski
Warsaw, Poland
^ permalink raw reply
* Re: [ANNOUNCE] Git wiki
From: Fredrik Kuivinen @ 2006-05-05 6:22 UTC (permalink / raw)
To: linux; +Cc: git
In-Reply-To: <20060505005659.9092.qmail@science.horizon.com>
On Thu, May 04, 2006 at 08:56:59PM -0400, linux@horizon.com wrote:
> What people who are asking for explicit rename tracking actually want
> is automatic rename merging. If branch A renames a file, and branch B
> corrects a typo on a comment somewhere, they'd like the merge to
> both patch and rename the file. If you can do that, you have met the
> need, even if your solution isn't the one the feature requester
> imagined.
I don't know if you already know this, if you do it might be valuable
for other readers.
If the rename is detected by the current rename detection code
(git-diff-tree -M) then the merge case described above is handled
perfectly fine by the current git. That is, the rename is followed and
the patch fixing the typo is applied to the renamed file. This assumes
that the default merge strategy (recursive) is used.
- Fredrik
^ permalink raw reply
* Re: [ANNOUNCE] Git wiki
From: Jakub Narebski @ 2006-05-05 6:26 UTC (permalink / raw)
To: git
In-Reply-To: <20060505062236.GA4544@c165.ib.student.liu.se>
Fredrik Kuivinen wrote:
> On Thu, May 04, 2006 at 08:56:59PM -0400, linux@horizon.com wrote:
>> What people who are asking for explicit rename tracking actually want
>> is automatic rename merging. If branch A renames a file, and branch B
>> corrects a typo on a comment somewhere, they'd like the merge to
>> both patch and rename the file. If you can do that, you have met the
>> need, even if your solution isn't the one the feature requester
>> imagined.
>
> I don't know if you already know this, if you do it might be valuable
> for other readers.
>
> If the rename is detected by the current rename detection code
> (git-diff-tree -M) then the merge case described above is handled
> perfectly fine by the current git. That is, the rename is followed and
> the patch fixing the typo is applied to the renamed file. This assumes
> that the default merge strategy (recursive) is used.
And if you do 'commit - rename, no changes - commit' sequence then rename
will be detected.
--
Jakub Narebski
Warsaw, Poland
^ permalink raw reply
* Re: [PATCH] binary patch.
From: Junio C Hamano @ 2006-05-05 6:47 UTC (permalink / raw)
To: Nicolas Pitre; +Cc: git
In-Reply-To: <Pine.LNX.4.64.0605042241240.28543@localhost.localdomain>
Nicolas Pitre <nico@cam.org> writes:
> On Thu, 4 May 2006, Junio C Hamano wrote:
>
>> This adds "binary patch" to the diff output and teaches apply
>> what to do with them.
>
> This is nice.
>
> However I'd deflate the delta data before encoding it with base85.
Yeah, things still to be done are deflating both delta and
optionally perhaps use just deflate without delta for "new file"
codepath.
And testsuite.
^ permalink raw reply
* Re: [PATCH] Fix linking with OpenSSL
From: Alexey Dobriyan @ 2006-05-05 7:57 UTC (permalink / raw)
To: Junio C Hamano; +Cc: git
In-Reply-To: <7vslnp2y5x.fsf@assigned-by-dhcp.cox.net>
On Thu, May 04, 2006 at 04:00:26PM -0700, Junio C Hamano wrote:
> Junio C Hamano <junkio@cox.net> writes:
> > Alexey Dobriyan <adobriyan@gmail.com> writes:
> >> For those who put it into interesting (read: default) place.
> >>
> >> Signed-off-by: Alexey Dobriyan <adobriyan@gmail.com>
> >>
> >> --- a/Makefile
> >> +++ b/Makefile
> >> @@ -559,7 +559,7 @@ git-http-push$X: revision.o http.o http-
> >>
> >> git-rev-list$X: rev-list.o $(LIB_FILE)
> >> $(CC) $(ALL_CFLAGS) -o $@ $(ALL_LDFLAGS) $(filter %.o,$^) \
> >> - $(LIBS) $(OPENSSL_LIBSSL)
> >> + $(LIBS) $(OPENSSL_LINK) $(OPENSSL_LIBSSL)
> >>
> >> init-db.o: init-db.c
> >> $(CC) -c $(ALL_CFLAGS) \
> >
> > We used to depend on bignum from openssl for rev-list
> > (merge-order), and if I remember correctly that was the only
> > reason built recipe for rev-list is different from other
> > programs. I wonder if we can just get rid of this thing, and
> > have it built with git-%$X rule like everybody else.
> >
> > Can somebody try that out and report what happens?
>
> Well, I did. Alexey, does this work for you?
It does. It also crashes busybox patch applet. Oh, well...
> --- a/Makefile
> +++ b/Makefile
> @@ -564,10 +564,6 @@ git-http-push$X: revision.o http.o http-
> $(CC) $(ALL_CFLAGS) -o $@ $(ALL_LDFLAGS) $(filter %.o,$^) \
> $(LIBS) $(CURL_LIBCURL) $(EXPAT_LIBEXPAT)
>
> -git-rev-list$X: rev-list.o $(LIB_FILE)
> - $(CC) $(ALL_CFLAGS) -o $@ $(ALL_LDFLAGS) $(filter %.o,$^) \
> - $(LIBS) $(OPENSSL_LIBSSL)
> -
> init-db.o: init-db.c
> $(CC) -c $(ALL_CFLAGS) \
> -DDEFAULT_GIT_TEMPLATE_DIR='"$(template_dir_SQ)"' $*.c
^ permalink raw reply
* Re: [PATCH] Fix linking with OpenSSL
From: Junio C Hamano @ 2006-05-05 8:02 UTC (permalink / raw)
To: Alexey Dobriyan; +Cc: git
In-Reply-To: <20060505075754.GA7237@mipter.zuzino.mipt.ru>
Alexey Dobriyan <adobriyan@gmail.com> writes:
> It does. It also crashes busybox patch applet. Oh, well...
Could you elaborate on "busybox patch" problem?
^ permalink raw reply
* Re: [ANNOUNCE] Git wiki
From: Petr Baudis @ 2006-05-05 9:23 UTC (permalink / raw)
To: Fredrik Kuivinen; +Cc: linux, git
In-Reply-To: <20060505062236.GA4544@c165.ib.student.liu.se>
Dear diary, on Fri, May 05, 2006 at 08:22:36AM CEST, I got a letter
where Fredrik Kuivinen <freku045@student.liu.se> said that...
> On Thu, May 04, 2006 at 08:56:59PM -0400, linux@horizon.com wrote:
> > What people who are asking for explicit rename tracking actually want
> > is automatic rename merging. If branch A renames a file, and branch B
> > corrects a typo on a comment somewhere, they'd like the merge to
> > both patch and rename the file. If you can do that, you have met the
> > need, even if your solution isn't the one the feature requester
> > imagined.
>
> I don't know if you already know this, if you do it might be valuable
> for other readers.
>
> If the rename is detected by the current rename detection code
> (git-diff-tree -M) then the merge case described above is handled
> perfectly fine by the current git. That is, the rename is followed and
> the patch fixing the typo is applied to the renamed file. This assumes
> that the default merge strategy (recursive) is used.
But the non-obviously important part here to note is that the branch B
merely "corrects a typo on a comment somewhere" - the latest versions in
branch A and branch B are always compared for renames, therefore if
branch A renamed the file and branch B sums up to some larger-scale
changes in the file, it still won't be merged properly.
--
Petr "Pasky" Baudis
Stuff: http://pasky.or.cz/
Right now I am having amnesia and deja-vu at the same time. I think
I have forgotten this before.
^ permalink raw reply
* Re: [ANNOUNCE] Git wiki
From: Junio C Hamano @ 2006-05-05 9:51 UTC (permalink / raw)
To: Petr Baudis; +Cc: git
In-Reply-To: <20060505092332.GY27689@pasky.or.cz>
Petr Baudis <pasky@suse.cz> writes:
> But the non-obviously important part here to note is that the branch B
> merely "corrects a typo on a comment somewhere" - the latest versions in
> branch A and branch B are always compared for renames, therefore if
> branch A renamed the file and branch B sums up to some larger-scale
> changes in the file, it still won't be merged properly.
I probably am guilty of starting this misinformation, but the
code does not compare the latest in A and B for rename
detection; it compares (O, A) and (O, B).
But the end result is the same - what you say is correct. If a
path (say O to A) that renamed has too big a change, then no
matter how small the changes are on the other path (O to B),
rename detection can be fooled. We could perhaps alleviate it
by following the whole commit chain.
^ permalink raw reply
* Re: [PATCH] binary patch.
From: Junio C Hamano @ 2006-05-05 10:15 UTC (permalink / raw)
To: Nicolas Pitre; +Cc: git
In-Reply-To: <7vwtd10xyd.fsf@assigned-by-dhcp.cox.net>
Junio C Hamano <junkio@cox.net> writes:
> Nicolas Pitre <nico@cam.org> writes:
>
>> This is nice.
>>
>> However I'd deflate the delta data before encoding it with base85.
>
> Yeah, things still to be done are deflating both delta and
> optionally perhaps use just deflate without delta for "new file"
> codepath.
>
> And testsuite.
-- >8 --
[PATCH] binary diff: further updates.
This updates the user interface and generated diff data format.
* "diff --binary" is used to signal that we want an e-mailable
binary patch. It implies --full-index and -p.
* "apply --allow-binary-replacement" acquired a short synonym
"apply --binary".
* After the "GIT binary patch\n" header line there is a token
to record which binary patch mechanism was used, so that we
can extend it later. Currently there are two mechanisms
defined: "literal" and "delta". The former records the
deflated postimage and the latter records the deflated delta
from the preimage to postimage.
For purely implementation convenience, I added the deflated
length after these "literal/delta" tokens (otherwise the
decoding side needs to guess and reallocate the buffer while
inflating). Improvement patches are very welcomed.
Signed-off-by: Junio C Hamano <junkio@cox.net>
---
* Have done only very minimum testing, and unlike somebody else ;-)
my code is not always perfect, so this will still stay out of
"next" for a while.
apply.c | 130 +++++++++++++++++++++++++++++++++++++++++++++----------------
cache.h | 1
diff.c | 135 +++++++++++++++++++++++++++++++++------------------------------
diff.h | 1
4 files changed, 169 insertions(+), 98 deletions(-)
diff --git a/apply.c b/apply.c
index e37c4eb..1b93aab 100644
--- a/apply.c
+++ b/apply.c
@@ -114,6 +114,9 @@ struct patch {
char *new_name, *old_name, *def_name;
unsigned int old_mode, new_mode;
int is_rename, is_copy, is_new, is_delete, is_binary;
+#define BINARY_DELTA_DEFLATED 1
+#define BINARY_LITERAL_DEFLATED 2
+ unsigned long deflate_origlen;
int lines_added, lines_deleted;
int score;
struct fragment *fragments;
@@ -969,9 +972,11 @@ static inline int metadata_changes(struc
static int parse_binary(char *buffer, unsigned long size, struct patch *patch)
{
- /* We have read "GIT binary patch\n"; what follows is a
- * sequence of 'length-byte' followed by base-85 encoded
- * delta data.
+ /* We have read "GIT binary patch\n"; what follows is a line
+ * that says the patch method (currently, either "deflated
+ * literal" or "deflated delta") and the length of data before
+ * deflating; a sequence of 'length-byte' followed by base-85
+ * encoded data follows.
*
* Each 5-byte sequence of base-85 encodes up to 4 bytes,
* and we would limit the patch line to 66 characters,
@@ -982,11 +987,27 @@ static int parse_binary(char *buffer, un
*/
int llen, used;
struct fragment *fragment;
- char *delta = NULL;
+ char *data = NULL;
- patch->is_binary = 1;
patch->fragments = fragment = xcalloc(1, sizeof(*fragment));
- used = 0;
+
+ /* Grab the type of patch */
+ llen = linelen(buffer, size);
+ used = llen;
+ linenr++;
+
+ if (!strncmp(buffer, "delta ", 6)) {
+ patch->is_binary = BINARY_DELTA_DEFLATED;
+ patch->deflate_origlen = strtoul(buffer + 6, NULL, 10);
+ }
+ else if (!strncmp(buffer, "literal ", 8)) {
+ patch->is_binary = BINARY_LITERAL_DEFLATED;
+ patch->deflate_origlen = strtoul(buffer + 8, NULL, 10);
+ }
+ else
+ return error("unrecognized binary patch at line %d: %.*s",
+ linenr-1, llen-1, buffer);
+ buffer += llen;
while (1) {
int byte_length, max_byte_length, newsize;
llen = linelen(buffer, size);
@@ -1015,8 +1036,8 @@ static int parse_binary(char *buffer, un
byte_length <= max_byte_length - 4)
goto corrupt;
newsize = fragment->size + byte_length;
- delta = xrealloc(delta, newsize);
- if (decode_85(delta + fragment->size,
+ data = xrealloc(data, newsize);
+ if (decode_85(data + fragment->size,
buffer + 1,
byte_length))
goto corrupt;
@@ -1024,7 +1045,7 @@ static int parse_binary(char *buffer, un
buffer += llen;
size -= llen;
}
- fragment->patch = delta;
+ fragment->patch = data;
return used;
corrupt:
return error("corrupt binary patch at line %d: %.*s",
@@ -1425,6 +1446,61 @@ #endif
return offset;
}
+static char *inflate_it(const void *data, unsigned long size,
+ unsigned long inflated_size)
+{
+ z_stream stream;
+ void *out;
+ int st;
+
+ memset(&stream, 0, sizeof(stream));
+
+ stream.next_in = (unsigned char *)data;
+ stream.avail_in = size;
+ stream.next_out = out = xmalloc(inflated_size);
+ stream.avail_out = inflated_size;
+ inflateInit(&stream);
+ st = inflate(&stream, Z_FINISH);
+ if ((st != Z_STREAM_END) || stream.total_out != inflated_size) {
+ free(out);
+ return NULL;
+ }
+ return out;
+}
+
+static int apply_binary_fragment(struct buffer_desc *desc, struct patch *patch)
+{
+ unsigned long dst_size;
+ struct fragment *fragment = patch->fragments;
+ void *data;
+ void *result;
+
+ data = inflate_it(fragment->patch, fragment->size,
+ patch->deflate_origlen);
+ if (!data)
+ return error("corrupt patch data");
+ switch (patch->is_binary) {
+ case BINARY_DELTA_DEFLATED:
+ result = patch_delta(desc->buffer, desc->size,
+ data,
+ patch->deflate_origlen,
+ &dst_size);
+ free(desc->buffer);
+ desc->buffer = result;
+ free(data);
+ break;
+ case BINARY_LITERAL_DEFLATED:
+ free(desc->buffer);
+ desc->buffer = data;
+ dst_size = patch->deflate_origlen;
+ break;
+ }
+ if (!desc->buffer)
+ return -1;
+ desc->size = desc->alloc = dst_size;
+ return 0;
+}
+
static int apply_binary(struct buffer_desc *desc, struct patch *patch)
{
const char *name = patch->old_name ? patch->old_name : patch->new_name;
@@ -1466,18 +1542,20 @@ static int apply_binary(struct buffer_de
"'%s' but it is not empty", name);
}
- if (desc->buffer) {
+ get_sha1_hex(patch->new_sha1_prefix, sha1);
+ if (!memcmp(sha1, null_sha1, 20)) {
free(desc->buffer);
desc->alloc = desc->size = 0;
- }
- get_sha1_hex(patch->new_sha1_prefix, sha1);
- if (!memcmp(sha1, null_sha1, 20))
+ desc->buffer = NULL;
return 0; /* deletion patch */
+ }
if (has_sha1_file(sha1)) {
+ /* We already have the postimage */
char type[10];
unsigned long size;
+ free(desc->buffer);
desc->buffer = read_sha1_file(sha1, type, &size);
if (!desc->buffer)
return error("the necessary postimage %s for "
@@ -1486,28 +1564,13 @@ static int apply_binary(struct buffer_de
desc->alloc = desc->size = size;
}
else {
- char type[10];
- unsigned long src_size, dst_size;
- void *src;
-
- get_sha1_hex(patch->old_sha1_prefix, sha1);
- src = read_sha1_file(sha1, type, &src_size);
- if (!src)
- return error("the necessary preimage %s for "
- "'%s' cannot be read",
- patch->old_sha1_prefix, name);
-
- /* patch->fragment->patch has the delta data and
- * we should apply it to the preimage.
+ /* We have verified desc matches the preimage;
+ * apply the patch data to it, which is stored
+ * in the patch->fragments->{patch,size}.
*/
- desc->buffer = patch_delta(src, src_size,
- (void*) patch->fragments->patch,
- patch->fragments->size,
- &dst_size);
- if (!desc->buffer)
+ if (apply_binary_fragment(desc, patch))
return error("binary patch does not apply to '%s'",
name);
- desc->size = desc->alloc = dst_size;
/* verify that the result matches */
write_sha1_file_prepare(desc->buffer, desc->size, blob_type,
@@ -2102,7 +2165,8 @@ int main(int argc, char **argv)
diffstat = 1;
continue;
}
- if (!strcmp(arg, "--allow-binary-replacement")) {
+ if (!strcmp(arg, "--allow-binary-replacement") ||
+ !strcmp(arg, "--binary")) {
allow_binary_replacement = 1;
continue;
}
diff --git a/cache.h b/cache.h
index 2f32f3d..4b7a439 100644
--- a/cache.h
+++ b/cache.h
@@ -365,5 +365,6 @@ extern void setup_pager(void);
/* base85 */
int decode_85(char *dst, char *line, int linelen);
+void encode_85(char *buf, unsigned char *data, int bytes);
#endif /* CACHE_H */
diff --git a/diff.c b/diff.c
index b14d897..94bd94a 100644
--- a/diff.c
+++ b/diff.c
@@ -392,78 +392,75 @@ static void show_stats(struct diffstat_t
total_files, adds, dels);
}
-static void *encode_delta_size(void *data, unsigned long size)
+static unsigned char *deflate_it(char *data,
+ unsigned long size,
+ unsigned long *result_size)
{
- unsigned char *cp = data;
- *cp++ = size;
- size >>= 7;
- while (size) {
- cp[-1] |= 0x80;
- *cp++ = size;
- size >>= 7;
- }
- return cp;
-}
-
-static void *safe_diff_delta(const unsigned char *src, unsigned long src_size,
- const unsigned char *dst, unsigned long dst_size,
- unsigned long *delta_size)
-{
- unsigned long bufsize;
- unsigned char *data;
- unsigned char *cp;
-
- if (src_size && dst_size)
- return diff_delta(src, src_size, dst, dst_size, delta_size, 0);
-
- /* diff-delta does not like to do delta with empty, so
- * we do that by hand here. Sigh...
- */
-
- if (!src_size)
- /* literal copy can be done only 127-byte at a time.
- */
- bufsize = dst_size + (dst_size / 127) + 40;
- else
- bufsize = 40;
- data = xmalloc(bufsize);
- cp = encode_delta_size(data, src_size);
- cp = encode_delta_size(cp, dst_size);
-
- if (dst_size) {
- /* copy out literally */
- while (dst_size) {
- int sz = (127 < dst_size) ? 127 : dst_size;
- *cp++ = sz;
- dst_size -= sz;
- while (sz) {
- *cp++ = *dst++;
- sz--;
- }
- }
- }
- *delta_size = (cp - data);
- return data;
+ int bound;
+ unsigned char *deflated;
+ z_stream stream;
+
+ memset(&stream, 0, sizeof(stream));
+ deflateInit(&stream, Z_BEST_COMPRESSION);
+ bound = deflateBound(&stream, size);
+ deflated = xmalloc(bound);
+ stream.next_out = deflated;
+ stream.avail_out = bound;
+
+ stream.next_in = (unsigned char *)data;
+ stream.avail_in = size;
+ while (deflate(&stream, Z_FINISH) == Z_OK)
+ ; /* nothing */
+ deflateEnd(&stream);
+ *result_size = stream.total_out;
+ return deflated;
}
static void emit_binary_diff(mmfile_t *one, mmfile_t *two)
{
- void *delta, *cp;
+ void *cp;
+ void *delta;
+ void *deflated;
+ void *data;
+ unsigned long orig_size;
unsigned long delta_size;
+ unsigned long deflate_size;
+ unsigned long data_size;
printf("GIT binary patch\n");
- delta = safe_diff_delta(one->ptr, one->size,
- two->ptr, two->size,
- &delta_size);
- if (!delta)
- die("unable to generate binary diff");
-
- /* emit delta encoded in base85 */
- cp = delta;
- while (delta_size) {
- int bytes = (52 < delta_size) ? 52 : delta_size;
+ /* We could do deflated delta, or we could do just deflated two,
+ * whichever is smaller.
+ */
+ delta = NULL;
+ deflated = deflate_it(two->ptr, two->size, &deflate_size);
+ if (one->size && two->size) {
+ delta = diff_delta(one->ptr, one->size,
+ two->ptr, two->size,
+ &delta_size, deflate_size);
+ orig_size = delta_size;
+ if (delta)
+ delta = deflate_it(delta, delta_size, &delta_size);
+ }
+
+ if (delta && delta_size < deflate_size) {
+ printf("delta %lu\n", orig_size);
+ free(deflated);
+ data = delta;
+ data_size = delta_size;
+ }
+ else {
+ printf("literal %lu\n", two->size);
+ free(delta);
+ data = deflated;
+ data_size = deflate_size;
+ }
+
+ /* emit data encoded in base85 */
+ cp = data;
+ while (data_size) {
+ int bytes = (52 < data_size) ? 52 : data_size;
char line[70];
- delta_size -= bytes;
+ data_size -= bytes;
if (bytes <= 26)
line[0] = bytes + 'A' - 1;
else
@@ -473,7 +470,7 @@ static void emit_binary_diff(mmfile_t *o
puts(line);
}
printf("\n");
- free(delta);
+ free(data);
}
#define FIRST_FEW_BYTES 8000
@@ -538,7 +535,11 @@ static void builtin_diff(const char *nam
die("unable to read files to diff");
if (mmfile_is_binary(&mf1) || mmfile_is_binary(&mf2)) {
- if (o->full_index)
+ /* Quite common confusing case */
+ if (mf1.size == mf2.size &&
+ !memcmp(mf1.ptr, mf2.ptr, mf1.size))
+ goto free_ab_and_return;
+ if (o->binary)
emit_binary_diff(&mf1, &mf2);
else
printf("Binary files %s and %s differ\n",
@@ -1239,6 +1240,10 @@ int diff_opt_parse(struct diff_options *
options->rename_limit = strtoul(arg+2, NULL, 10);
else if (!strcmp(arg, "--full-index"))
options->full_index = 1;
+ else if (!strcmp(arg, "--binary")) {
+ options->output_format = DIFF_FORMAT_PATCH;
+ options->full_index = options->binary = 1;
+ }
else if (!strcmp(arg, "--name-only"))
options->output_format = DIFF_FORMAT_NAME;
else if (!strcmp(arg, "--name-status"))
diff --git a/diff.h b/diff.h
index b3b2c4d..d052608 100644
--- a/diff.h
+++ b/diff.h
@@ -28,6 +28,7 @@ struct diff_options {
with_raw:1,
with_stat:1,
tree_in_recursive:1,
+ binary:1,
full_index:1,
silent_on_remove:1,
find_copies_harder:1;
--
1.3.1.g25a9
^ permalink raw reply related
* [PATCH/RFC (git-core)] squelch pack-object eye-candy on non-tty
From: Junio C Hamano @ 2006-05-05 10:20 UTC (permalink / raw)
To: git
One of my post-update scripts runs a git-fetch into a separate
repository and sends the results back to me (2>&1); I end up
getting this in the mail:
Generating pack...
Done counting 180 objects.
Result has 131 objects.
Deltifying 131 objects.
0% (0/131) done^M 1% (2/131) done^M...
This defaults not to do the progress report when not on a tty.
You could give --progress to force the progress report, but
let's not bother even documenting it nor mentioning it in the
usage string.
---
diff --git a/pack-objects.c b/pack-objects.c
index 6604338..53caed4 100644
--- a/pack-objects.c
+++ b/pack-objects.c
@@ -1239,6 +1239,7 @@ int main(int argc, char **argv)
setup_git_directory();
+ progress = isatty(2);
for (i = 1; i < argc; i++) {
const char *arg = argv[i];
@@ -1269,6 +1270,10 @@ int main(int argc, char **argv)
usage(pack_usage);
continue;
}
+ if (!strcmp("--progress", arg)) {
+ progress = 1;
+ continue;
+ }
if (!strcmp("-q", arg)) {
progress = 0;
continue;
^ permalink raw reply related
* Re: [PATCH/RFC (git-core)] squelch pack-object eye-candy on non-tty
From: Johannes Schindelin @ 2006-05-05 11:19 UTC (permalink / raw)
To: Junio C Hamano; +Cc: git
In-Reply-To: <7vmzdwzsar.fsf@assigned-by-dhcp.cox.net>
Hi,
On Fri, 5 May 2006, Junio C Hamano wrote:
> This defaults not to do the progress report when not on a tty.
Melikes,
Dscho
^ permalink raw reply
* [PATCH] Fix for config file section parsing.
From: sean @ 2006-05-05 13:49 UTC (permalink / raw)
To: git
Currently, if the target key has a section that matches
the initial substring of another section we mistakenly
believe we've found the correct section. To avoid this
problem, ensure that the section lengths are identical
before comparison.
Signed-off-by: Sean Estabrooks <seanlkml@sympatico.ca>
---
Here's an example of the problem:
$ git repo-config a.b.c d
$ cat .git/config
[a.b]
c = d
$ git repo-config a.x y
$ cat .git/config
[a.b]
c = d
x = y
config.c | 5 +++--
1 files changed, 3 insertions(+), 2 deletions(-)
f956fd1a6b1d3c82d9bc735427b58ec41d9e5dd1
diff --git a/config.c b/config.c
index 4e1f0c2..a3e14d7 100644
--- a/config.c
+++ b/config.c
@@ -335,8 +335,9 @@ static int store_aux(const char* key, co
store.offset[store.seen] = ftell(config_file);
store.state = KEY_SEEN;
store.seen++;
- } else if(!strncmp(key, store.key, store.baselen))
- store.state = SECTION_SEEN;
+ } else if (strrchr(key, '.') - key == store.baselen &&
+ !strncmp(key, store.key, store.baselen))
+ store.state = SECTION_SEEN;
}
return 0;
}
--
1.3.2.g2fb9
^ 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