* Re: Add specialized object allocator
From: Linus Torvalds @ 2006-06-19 18:10 UTC (permalink / raw)
To: Junio C Hamano, Git Mailing List
In-Reply-To: <Pine.LNX.4.64.0606191028540.5498@g5.osdl.org>
On Mon, 19 Jun 2006, Linus Torvalds wrote:
>
> It also allows us to track some basic statistics about object
> allocations. For example, for the mozilla import, it shows
> object usage as follows:
>
> blobs: 627629 (14710 kB)
> trees: 1119035 (34969 kB)
> commits: 196423 (8440 kB)
> tags: 1336 (46 kB)
Btw, this is the trivial additional patch to allow you to say
git --report rev-list --all --objects > /dev/null
and have it report object allocation usage after the op.
Useful? Probably not. It was useful for me to verify that everything
looked ok (and while I knew we had more trees than blobs, it's actually
interesting to see how projects differ.
The "git" tree, for example, has more blobs than trees: because it's a
fairly flat development tree, a commit that changes more than one file
will generate more new blobs than it generates trees.
In contrast, the kernel has about 30% more trees than blobs (but since
trees have the extra data/size fields, 30% extra trees take 75% more space
than blobs).
The mozilla import has a _lot_ more trees than blobs (80% more trees, and
they use up more than twice as much memory). It's probably a pretty deep
tree structure and/or they often commit changes to single files deep into
the tree).
Linus
----
diff --git a/git.c b/git.c
index 329ebec..6149499 100644
--- a/git.c
+++ b/git.c
@@ -271,6 +271,10 @@ int main(int argc, const char **argv, ch
puts(git_exec_path());
exit(0);
}
+ if (!strcmp(cmd, "report")) {
+ atexit(alloc_report);
+ continue;
+ }
cmd_usage(0, NULL, NULL);
}
argv[0] = cmd;
^ permalink raw reply related
* [PATCH] Make CSS file gitweb/gitweb.css more readable
From: Jakub Narebski @ 2006-06-19 18:27 UTC (permalink / raw)
To: git
Taken from git://git.xmms.se/xmms2/gitweb-xmms2.git
commit 561262030d58a6325f500b36d836dbe02a5abc68
"Make CSS readable" by Daniel Svensson, with extra
parts removed and consistent whitespace usage.
---
gitweb/gitweb.css | 273 +++++++++++++++++++++++++++++++++++++++++++----------
1 files changed, 223 insertions(+), 50 deletions(-)
72888c0a080d95117d54dc9578dc2a0de7b19abd
diff --git a/gitweb/gitweb.css b/gitweb/gitweb.css
index 5900916..9d91426 100644
--- a/gitweb/gitweb.css
+++ b/gitweb/gitweb.css
@@ -1,58 +1,231 @@
body {
- font-family: sans-serif; font-size: 12px; border:solid #d9d8d1; border-width:1px;
- margin:10px; background-color:#ffffff; color:#000000;
-}
-a { color:#0000cc; }
-a:hover, a:visited, a:active { color:#880000; }
-div.page_header { height:25px; padding:8px; font-size:18px; font-weight:bold; background-color:#d9d8d1; }
-div.page_header a:visited, a.header { color:#0000cc; }
-div.page_header a:hover { color:#880000; }
-div.page_nav { padding:8px; }
-div.page_nav a:visited { color:#0000cc; }
-div.page_path { padding:8px; border:solid #d9d8d1; border-width:0px 0px 1px}
-div.page_footer { height:17px; padding:4px 8px; background-color: #d9d8d1; }
-div.page_footer_text { float:left; color:#555555; font-style:italic; }
-div.page_body { padding:8px; }
+ font-family: sans-serif;
+ font-size: 12px;
+ border:solid #d9d8d1;
+ border-width: 1px;
+ margin: 10px;
+ background-color: #ffffff;
+ color: #000000;
+}
+
+a {
+ color: #0000cc;
+}
+
+a:hover, a:visited, a:active {
+ color: #880000;
+}
+
+div.page_header {
+ height: 25px;
+ padding: 8px;
+ font-size: 18px;
+ font-weight: bold;
+ background-color: #d9d8d1;
+}
+
+div.page_header a:visited, a.header {
+ color: #0000cc;
+}
+
+div.page_header a:hover {
+ color: #880000;
+}
+
+div.page_nav {
+ padding:8px;
+}
+
+div.page_nav a:visited {
+ color: #0000cc;
+}
+
+div.page_path {
+ padding: 8px;
+ border: solid #d9d8d1;
+ border-width: 0px 0px 1px;
+}
+
+div.page_footer {
+ height: 17px;
+ padding: 4px 8px;
+ background-color: #d9d8d1;
+}
+
+div.page_footer_text {
+ float: left;
+ color: #555555;
+ font-style: italic;
+}
+
+div.page_body {
+ padding: 8px;
+}
+
div.title, a.title {
- display:block; padding:6px 8px;
- font-weight:bold; background-color:#edece6; text-decoration:none; color:#000000;
+ display: block;
+ padding: 6px 8px;
+ font-weight: bold;
+ background-color: #edece6;
+ text-decoration: none;
+ color: #000000;
+}
+
+a.title:hover {
+ background-color: #d9d8d1;
+}
+
+div.title_text {
+ padding: 6px 0px;
+ border: solid #d9d8d1;
+ border-width: 0px 0px 1px;
}
-a.title:hover { background-color: #d9d8d1; }
-div.title_text { padding:6px 0px; border: solid #d9d8d1; border-width:0px 0px 1px; }
-div.log_body { padding:8px 8px 8px 150px; }
-span.age { position:relative; float:left; width:142px; font-style:italic; }
+
+div.log_body {
+ padding: 8px 8px 8px 150px;
+}
+
+span.age {
+ position: relative;
+ float: left;
+ width: 142px;
+ font-style:italic;
+}
+
div.log_link {
- padding:0px 8px;
- font-size:10px; font-family:sans-serif; font-style:normal;
- position:relative; float:left; width:136px;
-}
-div.list_head { padding:6px 8px 4px; border:solid #d9d8d1; border-width:1px 0px 0px; font-style:italic; }
-a.list { text-decoration:none; color:#000000; }
-a.list:hover { text-decoration:underline; color:#880000; }
-a.text { text-decoration:none; color:#0000cc; }
-a.text:visited { text-decoration:none; color:#880000; }
-a.text:hover { text-decoration:underline; color:#880000; }
-table { padding:8px 4px; }
-th { padding:2px 5px; font-size:12px; text-align:left; }
-tr.light:hover { background-color:#edece6; }
-tr.dark { background-color:#f6f6f0; }
-tr.dark:hover { background-color:#edece6; }
-td { padding:2px 5px; font-size:12px; vertical-align:top; }
-td.link { padding:2px 5px; font-family:sans-serif; font-size:10px; }
-div.pre { font-family:monospace; font-size:12px; white-space:pre; }
-div.diff_info { font-family:monospace; color:#000099; background-color:#edece6; font-style:italic; }
-div.index_include { border:solid #d9d8d1; border-width:0px 0px 1px; padding:12px 8px; }
-div.search { margin:4px 8px; position:absolute; top:56px; right:12px }
-a.linenr { color:#999999; text-decoration:none }
+ padding: 0px 8px;
+ font-size: 10px;
+ font-family: sans-serif;
+ font-style:normal;
+ position: relative;
+ float: left;
+ width: 136px;
+}
+
+div.list_head {
+ padding: 6px 8px 4px;
+ border: solid #d9d8d1;
+ border-width: 1px 0px 0px;
+ font-style: italic;
+}
+
+a.list {
+ text-decoration: none;
+ color: #000000;
+}
+
+a.list:hover {
+ text-decoration: underline;
+ color: #880000;
+}
+
+a.text {
+ text-decoration: none;
+ color: #0000cc;
+}
+
+a.text:visited {
+ text-decoration: none;
+ color: #880000;
+}
+
+a.text:hover {
+ text-decoration: underline;
+ color: #880000;
+}
+
+table {
+ padding: 8px 4px;
+}
+
+th {
+ padding: 2px 5px;
+ font-size: 12px;
+ text-align: left;
+}
+
+tr.light:hover {
+ background-color: #edece6;
+}
+
+tr.dark {
+ background-color: #f6f6f0;
+}
+
+tr.dark:hover {
+ background-color: #edece6;
+}
+
+
+td {
+ padding: 2px 5px;
+ font-size: 12px;
+ vertical-align:top;
+}
+
+td.link {
+ padding: 2px 5px;
+ font-family: sans-serif;
+ font-size: 10px;
+}
+
+div.pre {
+ font-family: monospace;
+ font-size: 12px;
+ white-space: pre;
+ /* padding-left: 5px; */
+}
+
+div.diff_info {
+ font-family: monospace;
+ color: #000099;
+ background-color: #edece6;
+ font-style: italic;
+}
+
+div.index_include {
+ border: solid #d9d8d1;
+ border-width: 0px 0px 1px;
+ padding: 12px 8px;
+}
+
+div.search {
+ margin: 4px 8px;
+ position: absolute;
+ top: 56px;
+ right: 12px
+}
+
+a.linenr {
+ color: #999999;
+ text-decoration: none
+}
+
a.rss_logo {
- float:right; padding:3px 0px; width:35px; line-height:10px;
- border:1px solid; border-color:#fcc7a5 #7d3302 #3e1a01 #ff954e;
- color:#ffffff; background-color:#ff6600;
- font-weight:bold; font-family:sans-serif; font-size:10px;
- text-align:center; text-decoration:none;
+ float: right;
+ padding: 3px 0px;
+ width: 35px;
+ line-height: 10px;
+ border: 1px solid;
+ border-color: #fcc7a5 #7d3302 #3e1a01 #ff954e;
+ color: #ffffff;
+ background-color: #ff6600;
+ font-weight: bold;
+ font-family: sans-serif;
+ font-size: 10px;
+ text-align: center;
+ text-decoration: none;
+}
+
+a.rss_logo:hover {
+ background-color: #ee5500;
}
-a.rss_logo:hover { background-color:#ee5500; }
+
span.tag {
- padding:0px 4px; font-size:10px; font-weight:normal;
- background-color:#ffffaa; border:1px solid; border-color:#ffffcc #ffee00 #ffee00 #ffffcc;
+ padding: 0px 4px;
+ font-size: 10px;
+ font-weight: normal;
+ background-color: #ffffaa;
+ border: 1px solid;
+ border-color: #ffffcc #ffee00 #ffee00 #ffffcc;
}
--
1.3.0
^ permalink raw reply related
* [PATCH] Fix t8001-annotate and t8002-blame for ActiveState Perl
From: Dennis Stosberg @ 2006-06-19 19:40 UTC (permalink / raw)
To: Alex Riesen; +Cc: Junio C Hamano, git
In-Reply-To: <81b0412b0606190935g67581ebucf172acb36e53b02@mail.gmail.com>
There seems to be at least one implementation of Perl which requires the
user to specify an extension for backup files.
Reported by Alex Riesen.
Signed-off-by: Dennis Stosberg <dennis@stosberg.net>
---
What system and what version of ActivePerl do you use? I have just
tried ActivePerl 5.8.8 on Solaris and it does _not_ force the user
to make backups.
t/annotate-tests.sh | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/t/annotate-tests.sh b/t/annotate-tests.sh
index c04f0e1..03ed081 100644
--- a/t/annotate-tests.sh
+++ b/t/annotate-tests.sh
@@ -111,7 +111,7 @@ test_expect_success \
test_expect_success \
'some edit' \
- 'perl -pi -e "s/^1A.*\n$//; s/^3A/99/" file &&
+ 'perl -p -i.orig -e "s/^1A.*\n$//; s/^3A/99/" file &&
GIT_AUTHOR_NAME="D" git commit -a -m "edit"'
test_expect_success \
--
1.4.0
^ permalink raw reply related
* Re: Add specialized object allocator
From: Junio C Hamano @ 2006-06-19 19:44 UTC (permalink / raw)
To: Linus Torvalds; +Cc: Git Mailing List
In-Reply-To: <Pine.LNX.4.64.0606191028540.5498@g5.osdl.org>
Impressed. I wonder if we want to deal with any_object
structure as well.
^ permalink raw reply
* Re: [PATCH] Make CSS file gitweb/gitweb.css more readable
From: Junio C Hamano @ 2006-06-19 20:14 UTC (permalink / raw)
To: Jakub Narebski; +Cc: git
In-Reply-To: <e76qbi$tt9$1@sea.gmane.org>
Jakub, I've been applying your patches after hand-fixing but it
appears that there is serious whitespace breakage on the mail
path somewhere between you and the mailing list. Please check
your MUA.
For example:
> div.title, a.title {
> - display:block; padding:6px 8px;
> - font-weight:bold; background-color:#edece6; text-decoration:none; color:#000000;
The original indents these two lines with a TAB.
I'll hand-munge your patch again and will clean-up the
indentation and push the result out as part of "next" sometime
later.
Also I've removed the commented out "padding-left" in div.pre.
^ permalink raw reply
* Re: Add specialized object allocator
From: Linus Torvalds @ 2006-06-19 20:30 UTC (permalink / raw)
To: Junio C Hamano; +Cc: Git Mailing List
In-Reply-To: <7vejxl9bi0.fsf@assigned-by-dhcp.cox.net>
On Mon, 19 Jun 2006, Junio C Hamano wrote:
>
> Impressed. I wonder if we want to deal with any_object
> structure as well.
Well, it would certainly be very easily doable, but none of the core code
actually uses it, so it wasn't even on my radar.
Linus
^ permalink raw reply
* Re: [PATCH] Fix git to be (more) ANSI C99 compliant.
From: Florian Forster @ 2006-06-19 21:21 UTC (permalink / raw)
To: Linus Torvalds; +Cc: git
In-Reply-To: <Pine.LNX.4.64.0606180946090.5498@g5.osdl.org>
[-- Attachment #1: Type: text/plain, Size: 1256 bytes --]
On Sun, Jun 18, 2006 at 09:50:37AM -0700, Linus Torvalds wrote:
> > While most of this patch fixes void-pointer arithmetic
>
> This one I disagree with. Doing arithmetic on "void *" is _really_ useful,
Agreed: If you want to walk over the memory pointed to by a void-pointer
you want to do that byte-wise in the great majority of all cases.
> and I think most compilers end up supporting it either to be
> compatible with gcc, or just because it's hard to not do it.
Now this statement I don't agree with. (And by that I don't mean I
assume it to be false.)
I didn't start writing the patch because I like C99 so much. In fact, in
my opinion it introduces some possibilities I'd rather not have in C
because people might actually use them. But by default the Sun cc
complains about void-pointer arithmetic and I feel awkward to force the
compiler to accept broken code.
Maybe Rene Scharfe's method (as used in the patch to git-tar-tree) is a
good way around it? There are no explicit casts involved and standard-
compliant compilers like it, too. The downside is that you have two
variables for the same thing/memory.
Regards,
-octo
--
Florian octo Forster
Hacker in training
GnuPG: 0x91523C3D
http://verplant.org/
[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 189 bytes --]
^ permalink raw reply
* Re: Add specialized object allocator
From: Junio C Hamano @ 2006-06-19 21:38 UTC (permalink / raw)
To: Linus Torvalds; +Cc: Git Mailing List
In-Reply-To: <Pine.LNX.4.64.0606191327240.5498@g5.osdl.org>
Linus Torvalds <torvalds@osdl.org> writes:
> On Mon, 19 Jun 2006, Junio C Hamano wrote:
>>
>> Impressed. I wonder if we want to deal with any_object
>> structure as well.
>
> Well, it would certainly be very easily doable, but none of the core code
> actually uses it, so it wasn't even on my radar.
I think the definition of "the core" in your earlier message was
"stuff I [jc: Linus] use myself", and I think the above
statement is in line with that definition.
It is hereby officially declared that commit walkers are not
part of the core ;-).
Even the commit walker uses lookup_unknown only for the starting
object and all the rest are of known type, so it does not help
even if we did "union any_object" that much.
^ permalink raw reply
* Re: [PATCH] rebase: Allow merge strategies to be used when rebasing
From: Eric Wong @ 2006-06-19 21:39 UTC (permalink / raw)
To: Junio C Hamano; +Cc: git
In-Reply-To: <7vd5d63k7f.fsf@assigned-by-dhcp.cox.net>
Junio C Hamano <junkio@cox.net> wrote:
> Eric Wong <normalperson@yhbt.net> writes:
>
> > This solves the problem of rebasing local commits against an
> > upstream that has renamed files.
>
> I think leveraging the merge strategy to perform rebase is
> sound, but the selection of merge base for this purpose is quite
> different from the regular merge, and I think unfortunately this
> patch is probably wrong in letting git-merge choose the merge
> base.
>
> But let's mention other things as well.
>
> - You kept the original "format-patch piped to am" workflow
> optionally working.
I left it as the default, too. I figured that it's best not
to change the default (and most likely faster) behavior of
something people rely on.
> - You check if merge or patch was used for failed rebase and
> follow the appropriate codepath while resuming, which is
> good.
>
> - The list of commits you generate with tac seem to include
> merge commit -- you may want to give --no-merges to
> rev-list.
Good point, I'll change it.
> - I do not think we use "tac" elsewhere -- is it portable
> enough?
Nope. perl -e 'print reverse <>' is equivalent and we already use
plenty of perl.
> - Exiting with success unconditionally after "git am" feels
> wrong. I would do "exit $?" instead of "exit 0" there.
Oops, I'll change that, too.
> Suppose you have this commit ancestry graph:
>
> ----------------------------------------------------------------
> Example: git-rebase --onto master A topic
>
> A---B---C topic B'--C' topic
> / --> /
> D---E---F---G master D---E---F---G master
> ----------------------------------------------------------------
>
> This is slightly different from the one at the beginning of the
> script. The idea is A turned out to be not so cool, and we
> would want to drop it.
>
> > +call_merge () {
> > + cmt="$(cat $dotest/`printf %0${prec}d $1`)"
> > + echo "$cmt" > "$dotest/current"
> > + git-merge $strategy_args "rebase-merge: $cmt" HEAD "$cmt" \
> > + || die "$MRESOLVEMSG"
> > +}
>
> call_merge is first called with B in cmt, and HEAD is pointing
> at G. But the merge in this function makes a merge between B
> and G, taking the effect of E->A.
>
> I think the three-way merge you would want here is not between B
> and G using E as the pivot, but between B and G using A as the
> pivot. That's how cherry-pick and revert works. I would
> leverage the interface that is one level lower for this -- the
> strategy modules themselves.
>
> git-merge-$strategy $cmt^ -- HEAD $cmt
Changing the 'git-merge $strategy_args "rebase-merge: $cmt" HEAD "$cmt"'
line in call_merge() to this seems to have broken more tests.
I'm not an expert at merging strategies by any measure, I've just
trusted merge-recursive to Do The Right Thing(TM) more often than not,
and use rerere to avoid repeating work.
I'm not entirely sure I want (or fully understand how) to support
cherry-picking/revert with this, as I've already dropped --skip when
--merge was in use.
I'll think about this some more when I'm less distracted.
> The strategy modules take merge base(s), double-dash as the
> separator, our head and the other head. They do not make commit
> themselves (instead they leave working tree and index in
> committable state) and signal the results with their exit
> status:
>
> 0 -- success
> 1 -- conflicts
> 2 -- did not handle the merge at all
Cool, that's good.
--
Eric Wong
^ permalink raw reply
* Re: [PATCH] rebase: Allow merge strategies to be used when rebasing
From: Junio C Hamano @ 2006-06-19 21:55 UTC (permalink / raw)
To: Eric Wong; +Cc: git
In-Reply-To: <20060619213951.GA6987@hand.yhbt.net>
Eric Wong <normalperson@yhbt.net> writes:
> Junio C Hamano <junkio@cox.net> wrote:
>
>> - You kept the original "format-patch piped to am" workflow
>> optionally working.
>
> I left it as the default, too. I figured that it's best not
> to change the default (and most likely faster) behavior of
> something people rely on.
I should have said: "You kept ... working, which is good".
>> I think the three-way merge you would want here is not between B
>> and G using E as the pivot, but between B and G using A as the
>> pivot. That's how cherry-pick and revert works. I would
>> leverage the interface that is one level lower for this -- the
>> strategy modules themselves.
>>
>> git-merge-$strategy $cmt^ -- HEAD $cmt
>
> Changing the 'git-merge $strategy_args "rebase-merge: $cmt" HEAD "$cmt"'
> line in call_merge() to this seems to have broken more tests.
Oh, that is to be expected if you changed git-merge -s recursive
with git-merge-recursive without other changes. The former
makes a commit (which your original patch later used to create a
separate commit chain and discarded); the latter does not make a
commit but expects the caller to create a commit out of the
resulting index file.
> I'm not an expert at merging strategies by any measure, I've just
> trusted merge-recursive to Do The Right Thing(TM) more often than not,
> and use rerere to avoid repeating work.
I was originally hoping that rebasing would just be a matter of
listing sequence of commits to be ported onto a new base and
running "git-cherry-pick" on each of them in sequence. Now
cherry-pick does not use merge machinery (hence does not use
git-merge-recursive), but if we change that then updating rebase
would be pretty much straightforward. It just needs a UI layer
to guide the user through recovery process when the merge does
not resolve cleanly in the middle, no?
^ permalink raw reply
* [PATCH] Fix setting config variables with an alternative GIT_CONFIG
From: Johannes Schindelin @ 2006-06-19 22:51 UTC (permalink / raw)
To: git, junkio
When setting a config variable, git_config_set() ignored the variables
GIT_CONFIG and GIT_CONFIG_LOCAL. Now, when GIT_CONFIG_LOCAL is set, it
will write to that file. If not, GIT_CONFIG is checked, and only as a
fallback, the change is written to $GIT_DIR/config.
Add a test for it, and also future-proof the test for the upcoming
$HOME/.gitconfig support.
Signed-off-by: Johannes Schindelin <Johannes.Schindelin@gmx.de>
---
config.c | 15 ++++++++++++---
t/Makefile | 2 +-
t/t1300-repo-config.sh | 24 ++++++++++++++++++++++++
3 files changed, 37 insertions(+), 4 deletions(-)
diff --git a/config.c b/config.c
index d46eb6d..69aa05f 100644
--- a/config.c
+++ b/config.c
@@ -500,10 +500,19 @@ int git_config_set_multivar(const char*
int i, dot;
int fd = -1, in_fd;
int ret;
- char* config_filename = strdup(git_path("config"));
- char* lock_file = strdup(git_path("config.lock"));
+ char* config_filename;
+ char* lock_file;
const char* last_dot = strrchr(key, '.');
+ config_filename = getenv("GIT_CONFIG_LOCAL");
+ if (!config_filename) {
+ config_filename = getenv("GIT_CONFIG");
+ if (!config_filename)
+ config_filename = git_path("config");
+ }
+ config_filename = strdup(config_filename);
+ lock_file = strdup(mkpath("%s.lock", config_filename));
+
/*
* Since "key" actually contains the section name and the real
* key name separated by a dot, we have to know where the dot is.
@@ -610,7 +619,7 @@ int git_config_set_multivar(const char*
* As a side effect, we make sure to transform only a valid
* existing config file.
*/
- if (git_config(store_aux)) {
+ if (git_config_from_file(store_aux, config_filename)) {
fprintf(stderr, "invalid config file\n");
free(store.key);
if (store.value_regex != NULL) {
diff --git a/t/Makefile b/t/Makefile
index 5495985..632c55f 100644
--- a/t/Makefile
+++ b/t/Makefile
@@ -19,7 +19,7 @@ endif
all: $(T) clean
$(T):
- @echo "*** $@ ***"; '$(SHELL_PATH_SQ)' $@ $(GIT_TEST_OPTS)
+ @echo "*** $@ ***"; GIT_CONFIG=.git/config '$(SHELL_PATH_SQ)' $@ $(GIT_TEST_OPTS)
clean:
rm -fr trash
diff --git a/t/t1300-repo-config.sh b/t/t1300-repo-config.sh
index 8260d57..0de2497 100755
--- a/t/t1300-repo-config.sh
+++ b/t/t1300-repo-config.sh
@@ -309,5 +309,29 @@ EOF
test_expect_success 'new variable inserts into proper section' 'cmp .git/config expect'
+cat > other-config << EOF
+[ein]
+ bahn = strasse
+EOF
+
+cat > expect << EOF
+ein.bahn=strasse
+EOF
+
+GIT_CONFIG=other-config git-repo-config -l > output
+
+test_expect_success 'alternative GIT_CONFIG' 'cmp output expect'
+
+GIT_CONFIG=other-config git-repo-config anwohner.park ausweis
+
+cat > expect << EOF
+[ein]
+ bahn = strasse
+[anwohner]
+ park = ausweis
+EOF
+
+test_expect_success '--set in alternative GIT_CONFIG' 'cmp other-config expect'
+
test_done
--
1.4.0.g275f-dirty
^ permalink raw reply related
* [PATCH] Initialize lock_file struct to all zero.
From: Johannes Schindelin @ 2006-06-19 22:55 UTC (permalink / raw)
To: git, junkio
hold_lock_file_for_update() relies on that.
Signed-off-by: Johannes Schindelin <Johannes.Schindelin@gmx.de>
---
Bugs like this drive you crazy. You make a little change elsewhere,
and all of a sudden, a test of git-update-index fails (since the
lock file is never removed).
builtin-update-index.c | 2 +-
builtin-write-tree.c | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/builtin-update-index.c b/builtin-update-index.c
index 325cd09..829ed23 100644
--- a/builtin-update-index.c
+++ b/builtin-update-index.c
@@ -490,7 +490,7 @@ int cmd_update_index(int argc, const cha
git_config(git_default_config);
/* We can't free this memory, it becomes part of a linked list parsed atexit() */
- lock_file = xmalloc(sizeof(struct lock_file));
+ lock_file = xcalloc(1, sizeof(struct lock_file));
newfd = hold_lock_file_for_update(lock_file, get_index_file());
if (newfd < 0)
diff --git a/builtin-write-tree.c b/builtin-write-tree.c
index c3aac36..8c151da 100644
--- a/builtin-write-tree.c
+++ b/builtin-write-tree.c
@@ -16,7 +16,7 @@ int write_tree(unsigned char *sha1, int
int entries, was_valid, newfd;
/* We can't free this memory, it becomes part of a linked list parsed atexit() */
- struct lock_file *lock_file = xmalloc(sizeof(struct lock_file));
+ struct lock_file *lock_file = xcalloc(1, sizeof(struct lock_file));
newfd = hold_lock_file_for_update(lock_file, get_index_file());
--
1.4.0.g9833
^ permalink raw reply related
* git-svn: don't use the --rmdir feature with SVN libs
From: Eric Wong @ 2006-06-19 23:34 UTC (permalink / raw)
To: git
It's very broken when committing. It's off by default, and somehow my
tests didn't catch it. I'll fix it ASAP tonight.
Sorry if anybody else hit it before I did.
--
Eric Wong
^ permalink raw reply
* Re: [PATCH] Fix setting config variables with an alternative GIT_CONFIG
From: Johannes Schindelin @ 2006-06-19 23:46 UTC (permalink / raw)
To: git, junkio
In-Reply-To: <Pine.LNX.4.63.0606200050150.26329@wbgn013.biozentrum.uni-wuerzburg.de>
Hi,
On Tue, 20 Jun 2006, Johannes Schindelin wrote:
> + config_filename = getenv("GIT_CONFIG_LOCAL");
> + if (!config_filename) {
> + config_filename = getenv("GIT_CONFIG");
Oops. At the other places, GIT_CONFIG overrides GIT_CONFIG_LOCAL, so these
two must be exchanged in the patch.
Sorry,
Dscho
^ permalink raw reply
* [PATCH] Read configuration also from $HOME/.gitconfig
From: Johannes Schindelin @ 2006-06-19 23:48 UTC (permalink / raw)
To: git, junkiot
This patch is based on Pasky's, with three notable differences:
- I did not yet update the documentation
- I named it .gitconfig, not .gitrc
- git-repo-config does not barf when a unique key is overridden locally
The last means that if you have something like
[alias]
l = log --stat -M
in ~/.gitconfig, and
[alias]
l = log --stat -M next..
in $GIT_DIR/config, then
git-repo-config alias.l
returns only one value, namely the value from $GIT_DIR/config.
If you set the environment variable GIT_CONFIG, $HOME/.gitconfig is not
read, and neither $GIT_DIR/config, but $GIT_CONFIG instead.
If you set GIT_CONFIG_LOCAL instead, it is interpreted instead of
$GIT_DIR/config, but $HOME/.gitconfig is still read.
Signed-off-by: Johannes Schindelin <Johannes.Schindelin@gmx.de>
---
config.c | 34 +++++++++++++++++++++++++---------
repo-config.c | 39 +++++++++++++++++++++++++++++++++------
2 files changed, 58 insertions(+), 15 deletions(-)
diff --git a/config.c b/config.c
index 69aa05f..edbe5ed 100644
--- a/config.c
+++ b/config.c
@@ -317,17 +317,33 @@ int git_config_from_file(config_fn_t fn,
int git_config(config_fn_t fn)
{
- const char *filename = git_path("config");
- /* Forward-compatibility cue: $GIT_CONFIG makes git read _only_
- * the given config file, $GIT_CONFIG_LOCAL will make it process
- * it in addition to the global config file, the same way it would
- * the per-repository config file otherwise. */
- if (getenv("GIT_CONFIG")) {
- filename = getenv("GIT_CONFIG");
- } else if (getenv("GIT_CONFIG_LOCAL")) {
+ int ret = 0;
+ char *repo_config = NULL;
+ const char *home = NULL, *filename;
+
+ /* $GIT_CONFIG makes git read _only_ the given config file,
+ * $GIT_CONFIG_LOCAL will make it process it in addition to the
+ * global config file, the same way it would the per-repository
+ * config file otherwise. */
+ filename = getenv("GIT_CONFIG");
+ if (!filename) {
+ home = getenv("HOME");
filename = getenv("GIT_CONFIG_LOCAL");
+ if (!filename)
+ filename = repo_config = strdup(git_path("config"));
}
- return git_config_from_file(fn, filename);
+
+ if (home) {
+ const char *user_config = strdup(mkpath("%s/.gitconfig", home));
+ if (access(user_config, R_OK) > 0)
+ ret = git_config_from_file(fn, user_config);
+ free(user_config);
+ }
+
+ ret += git_config_from_file(fn, filename);
+ if (repo_config)
+ free(repo_config);
+ return ret;
}
/*
diff --git a/repo-config.c b/repo-config.c
index 08fc4cc..03f108f 100644
--- a/repo-config.c
+++ b/repo-config.c
@@ -64,7 +64,22 @@ static int show_config(const char* key_,
static int get_value(const char* key_, const char* regex_)
{
+ int ret = -1;
char *tl;
+ char *global = NULL, *repo_config = NULL;
+ const char *local;
+
+ local = getenv("GIT_CONFIG");
+ if (!local) {
+ const char *home = getenv("HOME");
+ local = getenv("GIT_CONFIG_LOCAL");
+ if (!local)
+ local = repo_config;
+ else
+ local = repo_config = strdup(git_path("config"));
+ if (home)
+ global = strdup(mkpath("%s/.gitconfig", home));
+ }
key = strdup(key_);
for (tl=key+strlen(key)-1; tl >= key && *tl != '.'; --tl)
@@ -76,7 +91,7 @@ static int get_value(const char* key_, c
key_regexp = (regex_t*)malloc(sizeof(regex_t));
if (regcomp(key_regexp, key, REG_EXTENDED)) {
fprintf(stderr, "Invalid key pattern: %s\n", key_);
- return -1;
+ goto free_strings;
}
}
@@ -89,11 +104,16 @@ static int get_value(const char* key_, c
regexp = (regex_t*)malloc(sizeof(regex_t));
if (regcomp(regexp, regex_, REG_EXTENDED)) {
fprintf(stderr, "Invalid pattern: %s\n", regex_);
- return -1;
+ goto free_strings;
}
}
- git_config(show_config);
+ if (do_all && global)
+ git_config_from_file(show_config, global);
+ git_config_from_file(show_config, local);
+ if (!do_all && !seen && global)
+ git_config_from_file(show_config, global);
+
free(key);
if (regexp) {
regfree(regexp);
@@ -101,9 +121,16 @@ static int get_value(const char* key_, c
}
if (do_all)
- return !seen;
-
- return (seen == 1) ? 0 : 1;
+ ret = !seen;
+ else
+ ret = (seen == 1) ? 0 : 1;
+
+free_strings:
+ if (repo_config)
+ free(repo_config);
+ if (global)
+ free(global);
+ return ret;
}
int main(int argc, const char **argv)
--
1.4.0.g6685
^ permalink raw reply related
* [Q] what to do when waitpid() returns ECHILD under signal(SIGCHLD, SIG_IGN)?
From: Junio C Hamano @ 2006-06-19 23:49 UTC (permalink / raw)
To: git; +Cc: Linus Torvalds
Somebody I met last week in Japan reported that the socks client
he uses to cross the firewall to connect to git:// port from his
company environment seems to do signal(SIGCHLD, SIG_IGN) before
spawning git. When "git clone" is invoked this way, we get a
mysterious failure.
I can reproduce the problem without using funny socks client
like this:
: gitster; trap '' SIGCHLD
: gitster; git clone git://git.kernel.org/pub/scm/git/git.git/ foo.git
error: waitpid failed (No child processes)
fetch-pack from 'git://git.kernel.org/pub/scm/git/git.git/' failed.
: gitster; ls foo.git
ls: foo.git: No such file or directory
We could work this around by having signal(SIGCHLD, SIG_DFL)
upfront in git.c::main(), but I am wondering what the standard
practice for programs that use waitpid() call. Do they protect
themselves from this in order to reliably obtain child exit
status? Or do they simply consider it is a user error to run a
program that use waitpid() with SIGCHLD ignored?
http://www.opengroup.org/onlinepubs/009695399/functions/waitpid.html
explicitly says this is an expected behaviour, so barfing upon
ECHILD sounds like a bug on our part.
^ permalink raw reply
* Re: [Q] what to do when waitpid() returns ECHILD under signal(SIGCHLD, SIG_IGN)?
From: Linus Torvalds @ 2006-06-19 23:57 UTC (permalink / raw)
To: Junio C Hamano; +Cc: git
In-Reply-To: <7vwtbc7ll6.fsf@assigned-by-dhcp.cox.net>
On Mon, 19 Jun 2006, Junio C Hamano wrote:
>
> Somebody I met last week in Japan reported that the socks client
> he uses to cross the firewall to connect to git:// port from his
> company environment seems to do signal(SIGCHLD, SIG_IGN) before
> spawning git.
Ok, that sounds pretty broken of it.
> We could work this around by having signal(SIGCHLD, SIG_DFL)
> upfront in git.c::main(), but I am wondering what the standard
> practice for programs that use waitpid() call.
We need the status return, so failing on getting ECHILD is absolutely the
right thing to do, because it implies that we don't know what the status
could have been.
So we need to reset SIGCHLD back to SIG_DFL (or catch it explicitly).
Whether we want to do that in the main() routine or when we actually do
the fork() or whatever is a different issue.
Linus
^ permalink raw reply
* Re: [PATCH] Initialize lock_file struct to all zero.
From: Junio C Hamano @ 2006-06-20 0:04 UTC (permalink / raw)
To: Johannes Schindelin; +Cc: git
In-Reply-To: <Pine.LNX.4.63.0606200054290.26329@wbgn013.biozentrum.uni-wuerzburg.de>
Good catch. Thanks.
^ permalink raw reply
* Packing empty subtrees: good/bad/indifferent?
From: Shawn Pearce @ 2006-06-20 0:09 UTC (permalink / raw)
To: git
So in my Eclipse plugin/Java GIT implementation I'm trying to figure
out what to do if the API caller feeds me a subtree which is empty.
Core GIT won't store an empty subtree simply because the subtree
can't exist in the index without at least one file in the tree.
But my Java implementation doesn't suffer from that limitation and
will happily store an empty subtree (and checkout an empty directory)
if that is what the caller gave it. :-)
In the plugin's UI level I'm trying relatively hard to refuse putting
an empty directory into the repository as an empty subtree but I'm
now wondering if I should enforce that even lower (like down in
the actual tree writer) just to be on the safe side.
Anyone have two cents they could share on the matter?
--
Shawn.
^ permalink raw reply
* Re: [Q] what to do when waitpid() returns ECHILD under signal(SIGCHLD, SIG_IGN)?
From: Junio C Hamano @ 2006-06-20 0:36 UTC (permalink / raw)
To: Linus Torvalds; +Cc: git
In-Reply-To: <Pine.LNX.4.64.0606191654590.5498@g5.osdl.org>
Linus Torvalds <torvalds@osdl.org> writes:
> Whether we want to do that in the main() routine or when we actually do
> the fork() or whatever is a different issue.
I do not offhand think of a place where we do fork() but not
waitpid(), and it is very tempting to cheat and do that in the
main(), since I do not see a downside to it.
^ permalink raw reply
* Add "named object array" concept
From: Linus Torvalds @ 2006-06-20 0:42 UTC (permalink / raw)
To: Junio C Hamano, Git Mailing List
We've had this notion of a "object_list" for a long time, which eventually
grew a "name" member because some users (notably git-rev-list) wanted to
name each object as it is generated.
That object_list is great for some things, but it isn't all that wonderful
for others, and the "name" member is generally not used by everybody.
This patch splits the users of the object_list array up into two: the
traditional list users, who want the list-like format, and who don't
actually use or want the name. And another class of users that really used
the list as an extensible array, and generally wanted to name the objects.
The patch is fairly straightforward, but it's also biggish. Most of it
really just cleans things up: switching the revision parsing and listing
over to the array makes things like the builtin-diff usage much simpler
(we now see exactly how many members the array has, and we don't get the
objects reversed from the order they were on the command line).
One of the main reasons for doing this at all is that the malloc overhead
of the simple object list was actually pretty high, and the array is just
a lot denser. So this patch brings down memory usage by git-rev-list by
just under 3% (on top of all the other memory use optimizations) on the
mozilla archive.
It does add more lines than it removes, and more importantly, it adds a
whole new infrastructure for maintaining lists of objects, but on the
other hand, the new dynamic array code is pretty obvious. The change to
builtin-diff-tree.c shows a fairly good example of why an array interface
is sometimes more natural, and just much simpler for everybody.
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
---
Btw, somebody should really check my http-push conversion.
It actually used to set up the whole "name" thing, and it still has the
code for it, but there really is no point to it, and as far as I can tell,
it never _used_ it. It just had it because the code was copied from
git-rev-list, I suspect.
So there's room for further simplification there, but I wanted to leave
that part as a minimal patch, just because I don't use it, and while I'm
pretty damn sure that the "name" part was never actually used (the fact
that it compiles fine without any "name" in the object list at all is a
big hint ;), it should get somebody else looking over my diff. And
simplifying the code later.
builtin-diff-files.c | 2 +-
builtin-diff-index.c | 2 +-
builtin-diff-tree.c | 42 +++++++++------------------------
builtin-diff.c | 26 +++++++++++---------
builtin-grep.c | 16 +++++--------
builtin-log.c | 4 ++-
builtin-rev-list.c | 64 ++++++++++++++++++++++++++------------------------
diff-lib.c | 4 ++-
http-push.c | 28 +++++++++++++++-------
name-rev.c | 17 +++++++------
object.c | 17 +++++++++++++
object.h | 13 +++++++++-
revision.c | 33 ++++++++++++--------------
revision.h | 12 +++++----
14 files changed, 150 insertions(+), 130 deletions(-)
diff --git a/builtin-diff-files.c b/builtin-diff-files.c
index cebda82..5afc1d7 100644
--- a/builtin-diff-files.c
+++ b/builtin-diff-files.c
@@ -41,7 +41,7 @@ int cmd_diff_files(int argc, const char
* rev.max_count is reasonable (0 <= n <= 3),
* there is no other revision filtering parameters.
*/
- if (rev.pending_objects ||
+ if (rev.pending.nr ||
rev.min_age != -1 || rev.max_age != -1)
usage(diff_files_usage);
/*
diff --git a/builtin-diff-index.c b/builtin-diff-index.c
index 1958580..c42ef9a 100644
--- a/builtin-diff-index.c
+++ b/builtin-diff-index.c
@@ -32,7 +32,7 @@ int cmd_diff_index(int argc, const char
* Make sure there is one revision (i.e. pending object),
* and there is no revision filtering parameters.
*/
- if (!rev.pending_objects || rev.pending_objects->next ||
+ if (rev.pending.nr != 1 ||
rev.max_count != -1 || rev.min_age != -1 || rev.max_age != -1)
usage(diff_cache_usage);
return run_diff_index(&rev, cached);
diff --git a/builtin-diff-tree.c b/builtin-diff-tree.c
index 58cf658..3409a39 100644
--- a/builtin-diff-tree.c
+++ b/builtin-diff-tree.c
@@ -65,7 +65,6 @@ int cmd_diff_tree(int argc, const char *
char line[1000];
struct object *tree1, *tree2;
static struct rev_info *opt = &log_tree_opt;
- struct object_list *list;
int read_stdin = 0;
git_config(git_diff_config);
@@ -86,45 +85,28 @@ int cmd_diff_tree(int argc, const char *
}
/*
- * NOTE! "setup_revisions()" will have inserted the revisions
- * it parsed in reverse order. So if you do
- *
- * git-diff-tree a b
- *
- * the commit list will be "b" -> "a" -> NULL, so we reverse
- * the order of the objects if the first one is not marked
- * UNINTERESTING.
+ * NOTE! We expect "a ^b" to be equal to "a..b", so we
+ * reverse the order of the objects if the second one
+ * is marked UNINTERESTING.
*/
- nr_sha1 = 0;
- list = opt->pending_objects;
- if (list) {
- nr_sha1++;
- tree1 = list->item;
- list = list->next;
- if (list) {
- nr_sha1++;
- tree2 = tree1;
- tree1 = list->item;
- if (list->next)
- usage(diff_tree_usage);
- /* Switch them around if the second one was uninteresting.. */
- if (tree2->flags & UNINTERESTING) {
- struct object *tmp = tree2;
- tree2 = tree1;
- tree1 = tmp;
- }
- }
- }
-
+ nr_sha1 = opt->pending.nr;
switch (nr_sha1) {
case 0:
if (!read_stdin)
usage(diff_tree_usage);
break;
case 1:
+ tree1 = opt->pending.objects[0].item;
diff_tree_commit_sha1(tree1->sha1);
break;
case 2:
+ tree1 = opt->pending.objects[0].item;
+ tree2 = opt->pending.objects[1].item;
+ if (tree2->flags & UNINTERESTING) {
+ struct object *tmp = tree2;
+ tree2 = tree1;
+ tree1 = tmp;
+ }
diff_tree_sha1(tree1->sha1,
tree2->sha1,
"", &opt->diffopt);
diff --git a/builtin-diff.c b/builtin-diff.c
index 6ac3d4b..99a2f76 100644
--- a/builtin-diff.c
+++ b/builtin-diff.c
@@ -50,7 +50,7 @@ static int builtin_diff_files(struct rev
* specified rev.max_count is reasonable (0 <= n <= 3), and
* there is no other revision filtering parameter.
*/
- if (revs->pending_objects ||
+ if (revs->pending.nr ||
revs->min_age != -1 ||
revs->max_age != -1 ||
3 < revs->max_count)
@@ -172,7 +172,7 @@ static int builtin_diff_index(struct rev
* Make sure there is one revision (i.e. pending object),
* and there is no revision filtering parameters.
*/
- if (!revs->pending_objects || revs->pending_objects->next ||
+ if (revs->pending.nr != 1 ||
revs->max_count != -1 || revs->min_age != -1 ||
revs->max_age != -1)
usage(builtin_diff_usage);
@@ -181,10 +181,10 @@ static int builtin_diff_index(struct rev
static int builtin_diff_tree(struct rev_info *revs,
int argc, const char **argv,
- struct object_list *ent)
+ struct object_array_entry *ent)
{
const unsigned char *(sha1[2]);
- int swap = 1;
+ int swap = 0;
while (1 < argc) {
const char *arg = argv[1];
if (!strcmp(arg, "--raw"))
@@ -195,10 +195,10 @@ static int builtin_diff_tree(struct rev_
}
/* We saw two trees, ent[0] and ent[1].
- * unless ent[0] is unintesting, they are swapped
+ * if ent[1] is unintesting, they are swapped
*/
- if (ent[0].item->flags & UNINTERESTING)
- swap = 0;
+ if (ent[1].item->flags & UNINTERESTING)
+ swap = 1;
sha1[swap] = ent[0].item->sha1;
sha1[1-swap] = ent[1].item->sha1;
diff_tree_sha1(sha1[0], sha1[1], "", &revs->diffopt);
@@ -208,7 +208,7 @@ static int builtin_diff_tree(struct rev_
static int builtin_diff_combined(struct rev_info *revs,
int argc, const char **argv,
- struct object_list *ent,
+ struct object_array_entry *ent,
int ents)
{
const unsigned char (*parent)[20];
@@ -242,13 +242,14 @@ void add_head(struct rev_info *revs)
obj = parse_object(sha1);
if (!obj)
return;
- add_object(obj, &revs->pending_objects, NULL, "HEAD");
+ add_pending_object(revs, obj, "HEAD");
}
int cmd_diff(int argc, const char **argv, char **envp)
{
+ int i;
struct rev_info rev;
- struct object_list *list, ent[100];
+ struct object_array_entry ent[100];
int ents = 0, blobs = 0, paths = 0;
const char *path = NULL;
struct blobinfo blob[2];
@@ -281,7 +282,7 @@ int cmd_diff(int argc, const char **argv
/* Do we have --cached and not have a pending object, then
* default to HEAD by hand. Eek.
*/
- if (!rev.pending_objects) {
+ if (!rev.pending.nr) {
int i;
for (i = 1; i < argc; i++) {
const char *arg = argv[i];
@@ -294,7 +295,8 @@ int cmd_diff(int argc, const char **argv
}
}
- for (list = rev.pending_objects; list; list = list->next) {
+ for (i = 0; i < rev.pending.nr; i++) {
+ struct object_array_entry *list = rev.pending.objects+i;
struct object *obj = list->item;
const char *name = list->name;
int flags = (obj->flags & UNINTERESTING);
diff --git a/builtin-grep.c b/builtin-grep.c
index 9806499..6a240fb 100644
--- a/builtin-grep.c
+++ b/builtin-grep.c
@@ -657,7 +657,7 @@ int cmd_grep(int argc, const char **argv
int cached = 0;
int seen_dashdash = 0;
struct grep_opt opt;
- struct object_list *list, **tail, *object_list = NULL;
+ struct object_array list = { 0, 0, NULL };
const char *prefix = setup_git_directory();
const char **paths = NULL;
int i;
@@ -677,7 +677,6 @@ int cmd_grep(int argc, const char **argv
* that continues up to the -- (if exists), and then paths.
*/
- tail = &object_list;
while (1 < argc) {
const char *arg = argv[1];
argc--; argv++;
@@ -851,12 +850,9 @@ int cmd_grep(int argc, const char **argv
/* Is it a rev? */
if (!get_sha1(arg, sha1)) {
struct object *object = parse_object(sha1);
- struct object_list *elem;
if (!object)
die("bad object %s", arg);
- elem = object_list_insert(object, tail);
- elem->name = arg;
- tail = &elem->next;
+ add_object_array(object, arg, &list);
continue;
}
if (!strcmp(arg, "--")) {
@@ -881,16 +877,16 @@ int cmd_grep(int argc, const char **argv
paths[1] = NULL;
}
- if (!object_list)
+ if (!list.nr)
return !grep_cache(&opt, paths, cached);
if (cached)
die("both --cached and trees are given.");
- for (list = object_list; list; list = list->next) {
+ for (i = 0; i < list.nr; i++) {
struct object *real_obj;
- real_obj = deref_tag(list->item, NULL, 0);
- if (grep_object(&opt, paths, real_obj, list->name))
+ real_obj = deref_tag(list.objects[i].item, NULL, 0);
+ if (grep_object(&opt, paths, real_obj, list.objects[i].name))
hit = 1;
}
return !hit;
diff --git a/builtin-log.c b/builtin-log.c
index 9187fd3..5a8a50b 100644
--- a/builtin-log.c
+++ b/builtin-log.c
@@ -257,8 +257,8 @@ int cmd_format_patch(int argc, const cha
output_directory);
}
- if (rev.pending_objects && rev.pending_objects->next == NULL) {
- rev.pending_objects->item->flags |= UNINTERESTING;
+ if (rev.pending.nr == 1) {
+ rev.pending.objects[0].item->flags |= UNINTERESTING;
add_head(&rev);
}
diff --git a/builtin-rev-list.c b/builtin-rev-list.c
index 71353eb..63bad0e 100644
--- a/builtin-rev-list.c
+++ b/builtin-rev-list.c
@@ -99,26 +99,26 @@ static void show_commit(struct commit *c
}
}
-static struct object_list **process_blob(struct blob *blob,
- struct object_list **p,
- struct name_path *path,
- const char *name)
+static void process_blob(struct blob *blob,
+ struct object_array *p,
+ struct name_path *path,
+ const char *name)
{
struct object *obj = &blob->object;
if (!revs.blob_objects)
- return p;
+ return;
if (obj->flags & (UNINTERESTING | SEEN))
- return p;
+ return;
obj->flags |= SEEN;
name = strdup(name);
- return add_object(obj, p, path, name);
+ add_object(obj, p, path, name);
}
-static struct object_list **process_tree(struct tree *tree,
- struct object_list **p,
- struct name_path *path,
- const char *name)
+static void process_tree(struct tree *tree,
+ struct object_array *p,
+ struct name_path *path,
+ const char *name)
{
struct object *obj = &tree->object;
struct tree_desc desc;
@@ -126,14 +126,14 @@ static struct object_list **process_tree
struct name_path me;
if (!revs.tree_objects)
- return p;
+ return;
if (obj->flags & (UNINTERESTING | SEEN))
- return p;
+ return;
if (parse_tree(tree) < 0)
die("bad tree object %s", sha1_to_hex(obj->sha1));
obj->flags |= SEEN;
name = strdup(name);
- p = add_object(obj, p, path, name);
+ add_object(obj, p, path, name);
me.up = path;
me.elem = name;
me.elem_len = strlen(name);
@@ -143,57 +143,59 @@ static struct object_list **process_tree
while (tree_entry(&desc, &entry)) {
if (S_ISDIR(entry.mode))
- p = process_tree(lookup_tree(entry.sha1), p, &me, entry.path);
+ process_tree(lookup_tree(entry.sha1), p, &me, entry.path);
else
- p = process_blob(lookup_blob(entry.sha1), p, &me, entry.path);
+ process_blob(lookup_blob(entry.sha1), p, &me, entry.path);
}
free(tree->buffer);
tree->buffer = NULL;
- return p;
}
static void show_commit_list(struct rev_info *revs)
{
+ int i;
struct commit *commit;
- struct object_list *objects = NULL, **p = &objects, *pending;
+ struct object_array objects = { 0, 0, NULL };
while ((commit = get_revision(revs)) != NULL) {
- p = process_tree(commit->tree, p, NULL, "");
+ process_tree(commit->tree, &objects, NULL, "");
show_commit(commit);
}
- for (pending = revs->pending_objects; pending; pending = pending->next) {
+ for (i = 0; i < revs->pending.nr; i++) {
+ struct object_array_entry *pending = revs->pending.objects + i;
struct object *obj = pending->item;
const char *name = pending->name;
if (obj->flags & (UNINTERESTING | SEEN))
continue;
if (obj->type == TYPE_TAG) {
obj->flags |= SEEN;
- p = add_object(obj, p, NULL, name);
+ add_object_array(obj, name, &objects);
continue;
}
if (obj->type == TYPE_TREE) {
- p = process_tree((struct tree *)obj, p, NULL, name);
+ process_tree((struct tree *)obj, &objects, NULL, name);
continue;
}
if (obj->type == TYPE_BLOB) {
- p = process_blob((struct blob *)obj, p, NULL, name);
+ process_blob((struct blob *)obj, &objects, NULL, name);
continue;
}
die("unknown pending object %s (%s)", sha1_to_hex(obj->sha1), name);
}
- while (objects) {
+ for (i = 0; i < objects.nr; i++) {
+ struct object_array_entry *p = objects.objects + i;
+
/* An object with name "foo\n0000000..." can be used to
* confuse downstream git-pack-objects very badly.
*/
- const char *ep = strchr(objects->name, '\n');
+ const char *ep = strchr(p->name, '\n');
if (ep) {
- printf("%s %.*s\n", sha1_to_hex(objects->item->sha1),
- (int) (ep - objects->name),
- objects->name);
+ printf("%s %.*s\n", sha1_to_hex(p->item->sha1),
+ (int) (ep - p->name),
+ p->name);
}
else
- printf("%s %s\n", sha1_to_hex(objects->item->sha1), objects->name);
- objects = objects->next;
+ printf("%s %s\n", sha1_to_hex(p->item->sha1), p->name);
}
}
@@ -348,7 +350,7 @@ int cmd_rev_list(int argc, const char **
if ((!list &&
(!(revs.tag_objects||revs.tree_objects||revs.blob_objects) &&
- !revs.pending_objects)) ||
+ !revs.pending.nr)) ||
revs.diff)
usage(rev_list_usage);
diff --git a/diff-lib.c b/diff-lib.c
index 2183b41..d93cd55 100644
--- a/diff-lib.c
+++ b/diff-lib.c
@@ -329,8 +329,8 @@ int run_diff_index(struct rev_info *revs
}
mark_merge_entries();
- ent = revs->pending_objects->item;
- tree_name = revs->pending_objects->name;
+ ent = revs->pending.objects[0].item;
+ tree_name = revs->pending.objects[0].name;
tree = parse_tree_indirect(ent->sha1);
if (!tree)
return error("bad tree object %s", tree_name);
diff --git a/http-push.c b/http-push.c
index ba64f8f..0f02a55 100644
--- a/http-push.c
+++ b/http-push.c
@@ -1171,7 +1171,7 @@ static void one_remote_object(const char
obj->flags |= REMOTE;
if (!object_list_contains(objects, obj))
- add_object(obj, &objects, NULL, "");
+ object_list_insert(obj, &objects);
}
static void handle_lockprop_ctx(struct xml_ctx *ctx, int tag_closed)
@@ -1699,6 +1699,15 @@ static int locking_available(void)
return lock_flags;
}
+struct object_list **add_one_object(struct object *obj, struct object_list **p)
+{
+ struct object_list *entry = xmalloc(sizeof(struct object_list));
+ entry->item = obj;
+ entry->next = *p;
+ *p = entry;
+ return &entry->next;
+}
+
static struct object_list **process_blob(struct blob *blob,
struct object_list **p,
struct name_path *path,
@@ -1712,8 +1721,7 @@ static struct object_list **process_blob
return p;
obj->flags |= SEEN;
- name = strdup(name);
- return add_object(obj, p, path, name);
+ return add_one_object(obj, p);
}
static struct object_list **process_tree(struct tree *tree,
@@ -1735,7 +1743,7 @@ static struct object_list **process_tree
obj->flags |= SEEN;
name = strdup(name);
- p = add_object(obj, p, NULL, name);
+ p = add_one_object(obj, p);
me.up = path;
me.elem = name;
me.elem_len = strlen(name);
@@ -1756,8 +1764,9 @@ static struct object_list **process_tree
static int get_delta(struct rev_info *revs, struct remote_lock *lock)
{
+ int i;
struct commit *commit;
- struct object_list **p = &objects, *pending;
+ struct object_list **p = &objects;
int count = 0;
while ((commit = get_revision(revs)) != NULL) {
@@ -1767,15 +1776,16 @@ static int get_delta(struct rev_info *re
count += add_send_request(&commit->object, lock);
}
- for (pending = revs->pending_objects; pending; pending = pending->next) {
- struct object *obj = pending->item;
- const char *name = pending->name;
+ for (i = 0; i < revs->pending.nr; i++) {
+ struct object_array_entry *entry = revs->pending.objects + i;
+ struct object *obj = entry->item;
+ const char *name = entry->name;
if (obj->flags & (UNINTERESTING | SEEN))
continue;
if (obj->type == TYPE_TAG) {
obj->flags |= SEEN;
- p = add_object(obj, p, NULL, name);
+ p = add_one_object(obj, p);
continue;
}
if (obj->type == TYPE_TREE) {
diff --git a/name-rev.c b/name-rev.c
index c29b93e..586d842 100644
--- a/name-rev.c
+++ b/name-rev.c
@@ -128,8 +128,7 @@ static const char* get_rev_name(struct o
int main(int argc, char **argv)
{
- struct object_list *revs = NULL;
- struct object_list **walker = &revs;
+ struct object_array revs = { 0, 0, NULL };
int as_is = 0, all = 0, transform_stdin = 0;
setup_git_directory();
@@ -184,9 +183,7 @@ int main(int argc, char **argv)
if (cutoff > commit->date)
cutoff = commit->date;
- object_list_append((struct object *)commit, walker);
- (*walker)->name = *argv;
- walker = &((*walker)->next);
+ add_object_array((struct object *)commit, *argv, &revs);
}
for_each_ref(name_ref);
@@ -243,9 +240,13 @@ #define ishex(x) (isdigit((x)) || ((x) >
if (objs[i])
printf("%s %s\n", sha1_to_hex(objs[i]->sha1),
get_rev_name(objs[i]));
- } else
- for ( ; revs; revs = revs->next)
- printf("%s %s\n", revs->name, get_rev_name(revs->item));
+ } else {
+ int i;
+ for (i = 0; i < revs.nr; i++)
+ printf("%s %s\n",
+ revs.objects[i].name,
+ get_rev_name(revs.objects[i].item));
+ }
return 0;
}
diff --git a/object.c b/object.c
index e26e319..37784ce 100644
--- a/object.c
+++ b/object.c
@@ -200,3 +200,20 @@ int object_list_contains(struct object_l
}
return 0;
}
+
+void add_object_array(struct object *obj, const char *name, struct object_array *array)
+{
+ unsigned nr = array->nr;
+ unsigned alloc = array->alloc;
+ struct object_array_entry *objects = array->objects;
+
+ if (nr >= alloc) {
+ alloc = (alloc + 32) * 2;
+ objects = xrealloc(objects, alloc * sizeof(*objects));
+ array->alloc = alloc;
+ array->objects = objects;
+ }
+ objects[nr].item = obj;
+ objects[nr].name = name;
+ array->nr = ++nr;
+}
diff --git a/object.h b/object.h
index c537b4b..6f23a9a 100644
--- a/object.h
+++ b/object.h
@@ -4,7 +4,6 @@ #define OBJECT_H
struct object_list {
struct object *item;
struct object_list *next;
- const char *name;
};
struct object_refs {
@@ -13,6 +12,15 @@ struct object_refs {
struct object *ref[FLEX_ARRAY]; /* more */
};
+struct object_array {
+ unsigned int nr;
+ unsigned int alloc;
+ struct object_array_entry {
+ struct object *item;
+ const char *name;
+ } *objects;
+};
+
#define TYPE_BITS 3
#define FLAG_BITS 27
@@ -72,4 +80,7 @@ unsigned object_list_length(struct objec
int object_list_contains(struct object_list *list, struct object *obj);
+/* Object array handling .. */
+void add_object_array(struct object *obj, const char *name, struct object_array *array);
+
#endif /* OBJECT_H */
diff --git a/revision.c b/revision.c
index 7bff2a1..b963f2a 100644
--- a/revision.c
+++ b/revision.c
@@ -31,17 +31,12 @@ static char *path_name(struct name_path
return n;
}
-struct object_list **add_object(struct object *obj,
- struct object_list **p,
- struct name_path *path,
- const char *name)
+void add_object(struct object *obj,
+ struct object_array *p,
+ struct name_path *path,
+ const char *name)
{
- struct object_list *entry = xmalloc(sizeof(*entry));
- entry->item = obj;
- entry->next = *p;
- entry->name = path_name(path, name);
- *p = entry;
- return &entry->next;
+ add_object_array(obj, path_name(path, name), p);
}
static void mark_blob_uninteresting(struct blob *blob)
@@ -117,9 +112,9 @@ void mark_parents_uninteresting(struct c
}
}
-static void add_pending_object(struct rev_info *revs, struct object *obj, const char *name)
+void add_pending_object(struct rev_info *revs, struct object *obj, const char *name)
{
- add_object(obj, &revs->pending_objects, NULL, name);
+ add_object_array(obj, name, &revs->pending);
}
static struct object *get_reference(struct rev_info *revs, const char *name, const unsigned char *sha1, unsigned int flags)
@@ -836,7 +831,7 @@ int setup_revisions(int argc, const char
object = get_reference(revs, arg, sha1, flags ^ local_flags);
add_pending_object(revs, object, arg);
}
- if (def && !revs->pending_objects) {
+ if (def && !revs->pending.nr) {
unsigned char sha1[20];
struct object *object;
if (get_sha1(def, sha1))
@@ -868,11 +863,13 @@ int setup_revisions(int argc, const char
void prepare_revision_walk(struct rev_info *revs)
{
- struct object_list *list;
+ int nr = revs->pending.nr;
+ struct object_array_entry *list = revs->pending.objects;
- list = revs->pending_objects;
- revs->pending_objects = NULL;
- while (list) {
+ revs->pending.nr = 0;
+ revs->pending.alloc = 0;
+ revs->pending.objects = NULL;
+ while (--nr >= 0) {
struct commit *commit = handle_commit(revs, list->item, list->name);
if (commit) {
if (!(commit->object.flags & SEEN)) {
@@ -880,7 +877,7 @@ void prepare_revision_walk(struct rev_in
insert_by_date(commit, &revs->commits);
}
}
- list = list->next;
+ list++;
}
if (revs->no_walk)
diff --git a/revision.h b/revision.h
index 4020e25..c010a08 100644
--- a/revision.h
+++ b/revision.h
@@ -18,7 +18,7 @@ typedef void (prune_fn_t)(struct rev_inf
struct rev_info {
/* Starting list */
struct commit_list *commits;
- struct object_list *pending_objects;
+ struct object_array pending;
/* Basic information */
const char *prefix;
@@ -99,9 +99,11 @@ struct name_path {
const char *elem;
};
-extern struct object_list **add_object(struct object *obj,
- struct object_list **p,
- struct name_path *path,
- const char *name);
+extern void add_object(struct object *obj,
+ struct object_array *p,
+ struct name_path *path,
+ const char *name);
+
+extern void add_pending_object(struct rev_info *revs, struct object *obj, const char *name);
#endif
^ permalink raw reply related
* Re: [Q] what to do when waitpid() returns ECHILD under signal(SIGCHLD, SIG_IGN)?
From: Linus Torvalds @ 2006-06-20 0:44 UTC (permalink / raw)
To: Junio C Hamano; +Cc: git
In-Reply-To: <7vfyi07jf2.fsf@assigned-by-dhcp.cox.net>
On Mon, 19 Jun 2006, Junio C Hamano wrote:
>
> Linus Torvalds <torvalds@osdl.org> writes:
>
> > Whether we want to do that in the main() routine or when we actually do
> > the fork() or whatever is a different issue.
>
> I do not offhand think of a place where we do fork() but not
> waitpid(), and it is very tempting to cheat and do that in the
> main(), since I do not see a downside to it.
Yeah, it probably does make sense. That said, there are several "main()"
functions, so you'd still end up having to verify that we catch all the
paths.. Are all users of fork() built-in by now?
Linus
^ permalink raw reply
* Re: git-svn: don't use the --rmdir feature with SVN libs
From: Eric Wong @ 2006-06-20 0:48 UTC (permalink / raw)
To: git, Junio C Hamano
In-Reply-To: <20060619233424.GD3929@localdomain>
Fortunately, the fix is pretty simple. But yes, this is the
scariest bug in git-svn that's ever happened :x
^ permalink raw reply
* [PATCH] git-svn: fix --rmdir when using SVN:: libraries
From: Eric Wong @ 2006-06-20 0:48 UTC (permalink / raw)
To: git, Junio C Hamano; +Cc: Eric Wong
In-Reply-To: <11507645052855-git-send-email-normalperson@yhbt.net>
When tracking directories with nearly all of its files at
the most nested levels, --rmdir would accidentally go too
far when deleting.
Of course, we'll add a test for this condition, too.
Makefile: automatically run new tests as they appear in t/
Signed-off-by: Eric Wong <normalperson@yhbt.net>
---
contrib/git-svn/git-svn.perl | 15 +++++++++++----
contrib/git-svn/t/t0002-deep-rmdir.sh | 29 +++++++++++++++++++++++++++++
2 files changed, 40 insertions(+), 4 deletions(-)
diff --git a/contrib/git-svn/git-svn.perl b/contrib/git-svn/git-svn.perl
index da0ff9a..7e7f2f0 100755
--- a/contrib/git-svn/git-svn.perl
+++ b/contrib/git-svn/git-svn.perl
@@ -2841,13 +2841,20 @@ sub rmdirs {
exec qw/git-ls-tree --name-only -r -z/, $self->{c} or croak $!;
}
local $/ = "\0";
+ my @svn_path = split m#/#, $self->{svn_path};
while (<$fh>) {
chomp;
- $_ = $self->{svn_path} . '/' . $_;
- my ($dn) = ($_ =~ m#^(.*?)/?(?:[^/]+)$#);
- delete $rm->{$dn};
- last unless %$rm;
+ my @dn = (@svn_path, (split m#/#, $_));
+ while (pop @dn) {
+ delete $rm->{join '/', @dn};
+ }
+ unless (%$rm) {
+ close $fh;
+ return;
+ }
}
+ close $fh;
+
my ($r, $p, $bat) = ($self->{r}, $self->{pool}, $self->{bat});
foreach my $d (sort { $b =~ tr#/#/# <=> $a =~ tr#/#/# } keys %$rm) {
$self->close_directory($bat->{$d}, $p);
diff --git a/contrib/git-svn/t/t0002-deep-rmdir.sh b/contrib/git-svn/t/t0002-deep-rmdir.sh
new file mode 100755
index 0000000..d693d18
--- /dev/null
+++ b/contrib/git-svn/t/t0002-deep-rmdir.sh
@@ -0,0 +1,29 @@
+test_description='git-svn rmdir'
+. ./lib-git-svn.sh
+
+test_expect_success 'initialize repo' "
+ mkdir import &&
+ cd import &&
+ mkdir -p deeply/nested/directory/number/1 &&
+ mkdir -p deeply/nested/directory/number/2 &&
+ echo foo > deeply/nested/directory/number/1/file &&
+ echo foo > deeply/nested/directory/number/2/another &&
+ svn import -m 'import for git-svn' . $svnrepo &&
+ cd ..
+ "
+
+test_expect_success 'mirror via git-svn' "
+ git-svn init $svnrepo &&
+ git-svn fetch &&
+ git checkout -f -b test-rmdir remotes/git-svn
+ "
+
+test_expect_success 'Try a commit on rmdir' "
+ git rm -f deeply/nested/directory/number/2/another &&
+ git commit -a -m 'remove another' &&
+ git-svn commit --rmdir HEAD &&
+ svn ls -R $svnrepo | grep ^deeply/nested/directory/number/1
+ "
+
+
+test_done
--
1.4.GIT
^ permalink raw reply related
* [PATCH (fixed)] git-svn: fix --rmdir when using SVN:: libraries
From: Eric Wong @ 2006-06-20 0:59 UTC (permalink / raw)
To: git, Junio C Hamano; +Cc: Eric Wong
In-Reply-To: <11507645052855-git-send-email-normalperson@yhbt.net>
When tracking directories with nearly all of its files at
the most nested levels, --rmdir would accidentally go too
far when deleting.
Of course, we'll add a test for this condition, too.
Makefile: automatically run new tests as they appear in t/
Signed-off-by: Eric Wong <normalperson@yhbt.net>
---
Oops, I left out the Makefile change in the other patch, had the new
test file as +x
contrib/git-svn/Makefile | 3 +--
contrib/git-svn/git-svn.perl | 15 +++++++++++----
contrib/git-svn/t/t0002-deep-rmdir.sh | 29 +++++++++++++++++++++++++++++
3 files changed, 41 insertions(+), 6 deletions(-)
diff --git a/contrib/git-svn/Makefile b/contrib/git-svn/Makefile
index 6aedb10..7c20946 100644
--- a/contrib/git-svn/Makefile
+++ b/contrib/git-svn/Makefile
@@ -29,8 +29,7 @@ git-svn.html : git-svn.txt
asciidoc -b xhtml11 -d manpage \
-f ../../Documentation/asciidoc.conf $<
test: git-svn
- cd t && $(SHELL) ./t0000-contrib-git-svn.sh $(TEST_FLAGS)
- cd t && $(SHELL) ./t0001-contrib-git-svn-props.sh $(TEST_FLAGS)
+ cd t && for i in t????-*.sh; do $(SHELL) ./$$i $(TEST_FLAGS); done
# we can test NO_OPTIMIZE_COMMITS independently of LC_ALL
full-test:
diff --git a/contrib/git-svn/git-svn.perl b/contrib/git-svn/git-svn.perl
index da0ff9a..7e7f2f0 100755
--- a/contrib/git-svn/git-svn.perl
+++ b/contrib/git-svn/git-svn.perl
@@ -2841,13 +2841,20 @@ sub rmdirs {
exec qw/git-ls-tree --name-only -r -z/, $self->{c} or croak $!;
}
local $/ = "\0";
+ my @svn_path = split m#/#, $self->{svn_path};
while (<$fh>) {
chomp;
- $_ = $self->{svn_path} . '/' . $_;
- my ($dn) = ($_ =~ m#^(.*?)/?(?:[^/]+)$#);
- delete $rm->{$dn};
- last unless %$rm;
+ my @dn = (@svn_path, (split m#/#, $_));
+ while (pop @dn) {
+ delete $rm->{join '/', @dn};
+ }
+ unless (%$rm) {
+ close $fh;
+ return;
+ }
}
+ close $fh;
+
my ($r, $p, $bat) = ($self->{r}, $self->{pool}, $self->{bat});
foreach my $d (sort { $b =~ tr#/#/# <=> $a =~ tr#/#/# } keys %$rm) {
$self->close_directory($bat->{$d}, $p);
diff --git a/contrib/git-svn/t/t0002-deep-rmdir.sh b/contrib/git-svn/t/t0002-deep-rmdir.sh
new file mode 100644
index 0000000..d693d18
--- /dev/null
+++ b/contrib/git-svn/t/t0002-deep-rmdir.sh
@@ -0,0 +1,29 @@
+test_description='git-svn rmdir'
+. ./lib-git-svn.sh
+
+test_expect_success 'initialize repo' "
+ mkdir import &&
+ cd import &&
+ mkdir -p deeply/nested/directory/number/1 &&
+ mkdir -p deeply/nested/directory/number/2 &&
+ echo foo > deeply/nested/directory/number/1/file &&
+ echo foo > deeply/nested/directory/number/2/another &&
+ svn import -m 'import for git-svn' . $svnrepo &&
+ cd ..
+ "
+
+test_expect_success 'mirror via git-svn' "
+ git-svn init $svnrepo &&
+ git-svn fetch &&
+ git checkout -f -b test-rmdir remotes/git-svn
+ "
+
+test_expect_success 'Try a commit on rmdir' "
+ git rm -f deeply/nested/directory/number/2/another &&
+ git commit -a -m 'remove another' &&
+ git-svn commit --rmdir HEAD &&
+ svn ls -R $svnrepo | grep ^deeply/nested/directory/number/1
+ "
+
+
+test_done
--
1.4.GIT
^ 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