* Re: [PATCH 00/22] Refactor to accept NUL in commit messages
From: Jeff King @ 2011-10-27 23:44 UTC (permalink / raw)
To: Junio C Hamano; +Cc: git, Nguyen Thai Ngoc Duy, Ævar Arnfjörð
In-Reply-To: <7v39eez1ph.fsf@alter.siamese.dyndns.org>
On Thu, Oct 27, 2011 at 12:14:34PM -0700, Junio C Hamano wrote:
> > Minor nit, but this is just for diff, so it is not about clean/smudge
> > but rather about doing something like textconv.
>
> I can understand if some tools in the Windows land prefer to work with
> these encodings, so clean/smudge to have the checkout in these encodings
> would be a reasonable thing not just diff but things like grep. On the
> other hand, I do doubt the sanity of these people if they want to have
> in-repository representation also in these encodings.
I'm pretty much of the same mind. We do have people with utf-16 in their
repositories on github. I have no idea why they do such a thing, or what
kinds of tricks they do to make it usable (because without it, they just
get "binary files differ").
My interest is to make things like bare-repository diff (and everything
built on it; i.e., things like github, gitweb, or whatever) do the sane
thing for these people, even if I think what they're doing is wrong. And
as always, I try to structure the git portions of that as much as
possible to be general and help everybody, so they can be pushed
upstream (also, then I don't have to worry about managing local changes
:) ).
But it sounds like this is probably just too ugly and should end up as a
github-specific thing.
-Peff
^ permalink raw reply
* Re: [PATCH 00/22] Refactor to accept NUL in commit messages
From: Junio C Hamano @ 2011-10-28 0:03 UTC (permalink / raw)
To: Jeff King; +Cc: git, Nguyen Thai Ngoc Duy, Ævar Arnfjörð
In-Reply-To: <20111027234429.GA28187@sigill.intra.peff.net>
Jeff King <peff@peff.net> writes:
> My interest is to make things like bare-repository diff (and everything
> built on it; i.e., things like github, gitweb, or whatever) do the sane
> thing for these people, even if I think what they're doing is wrong.
I do not think we are talking about right or wrong. I was primarily saying
that textconv may not be the right thing (think github/gitweb showing blob
contents, nicely formatted inside the chrome the site provides).
The solution you suggested feels like a gross layering violation, unless
we do it everywhere, in which case I wouldn't mind too much.
We have in-repository representation that diff and grep and friends work
on, and output conversion layer that externalizes the result of them in
the form of "smudge". Another layer above the in-repository representation
and below operations could convert UTF-16 to UTF-8 when going outward and
in the opposite when going inward.
^ permalink raw reply
* Re: [PATCH 00/22] Refactor to accept NUL in commit messages
From: Jeff King @ 2011-10-28 0:19 UTC (permalink / raw)
To: Junio C Hamano; +Cc: git, Nguyen Thai Ngoc Duy, Ævar Arnfjörð
In-Reply-To: <7v1utyx9ri.fsf@alter.siamese.dyndns.org>
On Thu, Oct 27, 2011 at 05:03:29PM -0700, Junio C Hamano wrote:
> Jeff King <peff@peff.net> writes:
>
> > My interest is to make things like bare-repository diff (and everything
> > built on it; i.e., things like github, gitweb, or whatever) do the sane
> > thing for these people, even if I think what they're doing is wrong.
>
> I do not think we are talking about right or wrong. I was primarily saying
> that textconv may not be the right thing (think github/gitweb showing blob
> contents, nicely formatted inside the chrome the site provides).
But I think it is probably a wrong thing to store utf-16 as the
canonical format inside the git repository. Git simply can't handle it
for diffing. And the right thing, as you suggested, is clean/smudge.
But I'm dealing with repositories on the server side, where it is too
late to do clean/smudge; I just get whatever junk people commited.
> We have in-repository representation that diff and grep and friends work
> on, and output conversion layer that externalizes the result of them in
> the form of "smudge". Another layer above the in-repository representation
> and below operations could convert UTF-16 to UTF-8 when going outward and
> in the opposite when going inward.
I'm not sure that could sanely be done in a backwards compatible way.
Doing it with just textual diffs is a hack, of course, but at least we
know that the damage is limited, and the diff we generate on top doesn't
care that much about the original sha1s[1]. But should read_object_sha1
learn to convert utf-16 into utf-8? I think madness lies that way, as
we are breaking assumptions about sha1 validity.
-Peff
[1] Actually, the text diff does mention the original and resulting
sha1s, which would now either bear no relation to the diff text, or bear
no relation to what's in the repo. Either way, I think we are creating
something that can't necessarily be applied, which is bad. And is why I
thought of textconv, which is basically the same concept (and has the
same problems).
^ permalink raw reply
* Re: git alias and --help
From: Gelonida N @ 2011-10-28 0:24 UTC (permalink / raw)
To: git
In-Reply-To: <7v8vo6xd4u.fsf@alter.siamese.dyndns.org>
On 10/28/2011 12:50 AM, Junio C Hamano wrote:
> Junio C Hamano <gitster@pobox.com> writes:
>
>> Gelonida N <gelonida@gmail.com> writes:
>>
>>> Is there any trick to get the help text of git branch without
>>> having to type
>>>
>>> git branch --help
>>
>> How about "git help branch"?
>
> It was bad of me to write a tongue-in-cheek answer, get distracted and
> ended up sending it without the real answer.
No issues. At least I got an answer :-)
>
> The reason why we do not do what you seem to be suggesting is because
> giving the same behaviour to "git b --help" as "git branch --help" is
> wrong.
>
> To see why, imagine you have configured an alias that is not a simple and
> stupid substitution "b == branch", but something like "bt == branch -t",
> and then want to know what you should write after "git bt". Giving the
> manpage for branch without giving them any hint that they configured that
> alias to produce customized behaviour that is different from plain vanilla
> "branch" is not quite acceptable.
>
> I think you _could_ make a patch that special cases a simple and straight
> substitution and skip the "foo is aliased to bar" step, but I doubt it is
> worth it to lose consistency between "git b --help" vs "git bt --help"
> that way.
I understand the reasoning and agree, that as general case it might not
be a good idea to have the behaviour, taht I expected to be the default
behaviour
It's just, that I am lazy so I shortened my most common commands
For example:
co=checkout
ci=commit
b=branch
sm=submodule
However I'm not smart enough to remember all options for all commands
and so I have to ask git for occasional help.
It feels so 'unlazy' to have to type the full command 'just' to get help
What I wondered though is whether there couldn't be a way to be lazy and
avoid confusion.
1.) prompt for full help
-------------------------
One option would be to display what the command is aliased to and to
prompt whether one wants to see the full help of the base command.
`git b' is aliased to `branch'
pleaset press h if you want to see the full help for git branch
or press q to quit
2.) allow copy paste by displaying the command to be typed for help.
---------------------------------------------------------------------
display sometihing like:
`git b' is aliased to `branch'
for help about the branch command type: git --help
Then lazy people could copy paste the command instead of typing it.
3.) special alias syntax to allow 'forwarding' of --help
------------------------------------------------------------
some kind of special alias syntax, which explicitely forces that --help
is 'forwarded' to the alias and not treated by git
example:
b = branch # --help would have the current behaviour
I tried following to see whether '--help' is now being 'forwarded'
b = ! git branch
but also here --help is treated by git
A possibility could be another 'special' character. For the sake of the
example I used '?'
b = ?branch # 'the question mark would allow 'forwarding' the
# --help option to the alias'
b = ?! git branch
My workaround
------------
Fort the time being I might do something like
bhlp = branch --help
I would have prefered b_hlp or b_h, but it seems underscore isn't
allowed in an alias.
^ permalink raw reply
* Re: [PATCH 00/22] Refactor to accept NUL in commit messages
From: Miles Bader @ 2011-10-28 1:40 UTC (permalink / raw)
To: Jeff King
Cc: Junio C Hamano, git, Nguyen Thai Ngoc Duy,
Ævar Arnfjörð
In-Reply-To: <20111027234429.GA28187@sigill.intra.peff.net>
Jeff King <peff@peff.net> writes:
> We do have people with utf-16 in their repositories on github. I
> have no idea why they do such a thing, or what kinds of tricks they
> do to make it usable (because without it, they just get "binary
> files differ").
Hmm, you could ask them ... [or, I suppose more diplomatically, post
a blog entry asking "Hey all you people who use github for utf-16
encoded files, ..."]
-Miles
--
Year, n. A period of three hundred and sixty-five disappointments.
^ permalink raw reply
* Re: git alias and --help
From: Miles Bader @ 2011-10-28 1:51 UTC (permalink / raw)
To: Junio C Hamano; +Cc: Gelonida N, git
In-Reply-To: <7v8vo6xd4u.fsf@alter.siamese.dyndns.org>
Junio C Hamano <gitster@pobox.com> writes:
>>> git branch --help
>>
>> How about "git help branch"?
>
> The reason why we do not do what you seem to be suggesting is because
> giving the same behaviour to "git b --help" as "git branch --help" is
> wrong.
I agree with Gelonida's followup: although what you say makes sense,
it's still pretty annoying behavior for the very common case of a
simple renaming alias...
E.g., I have "co" aliased to "checkout", and so my fingers are very
very inclined to say "co" when I mean checkout... including when
asking for help. I actually end up typing "git co --help", grumbling,
and retyping with the full command name, quite reguarly.
What I've often wished is that git's help system would output
something like:
$ git help co
`git co' is aliased to `checkout'
Here's the help entry for `checkout':
GIT-CHECKOUT(1) Git Manual GIT-CHECKOUT(1)
NAME
git-checkout - Checkout a branch or paths to the working tree
...
[with the "`git co' is aliased ..." header included in the pager
output.]
Of course, that would be the wrong thing for somebody that just wants
to be reminded what an alias expands too, but my intuition is that
this is a very tiny minority compared to people that want to examine
the options for the underlying command...
-Miles
--
Suburbia: where they tear out the trees and then name streets after them.
^ permalink raw reply
* Re: git alias and --help
From: Junio C Hamano @ 2011-10-28 4:05 UTC (permalink / raw)
To: Miles Bader; +Cc: Gelonida N, git
In-Reply-To: <buoty6t9937.fsf@dhlpc061.dev.necel.com>
Miles Bader <miles@gnu.org> writes:
> Of course, that would be the wrong thing for somebody that just wants
> to be reminded what an alias expands too, but my intuition is that
> this is a very tiny minority compared to people that want to examine
> the options for the underlying command...
And it is doubly wrong if help backend is configured to be anything but
manpages, no?
As I said, you should be able to come up with a patch that detects and
special cases the no frills case (replacement to single token) to get what
you want.
^ permalink raw reply
* Re: [PATCH 00/22] Refactor to accept NUL in commit messages
From: Junio C Hamano @ 2011-10-28 4:07 UTC (permalink / raw)
To: Miles Bader
Cc: Jeff King, git, Nguyen Thai Ngoc Duy,
Ævar Arnfjörð
In-Reply-To: <buo39edao6r.fsf@dhlpc061.dev.necel.com>
Miles Bader <miles@gnu.org> writes:
> Jeff King <peff@peff.net> writes:
>> We do have people with utf-16 in their repositories on github. I
>> have no idea why they do such a thing, or what kinds of tricks they
>> do to make it usable (because without it, they just get "binary
>> files differ").
>
> Hmm, you could ask them ... [or, I suppose more diplomatically, post
> a blog entry asking "Hey all you people who use github for utf-16
> encoded files, ..."]
People will hate such a flag day event initially and later thank you for
it ;-)
I am afraid that that is a wishful thinking, though.
^ permalink raw reply
* [RFC/PATCH] define the way new representation types are encoded in the pack
From: Junio C Hamano @ 2011-10-28 6:04 UTC (permalink / raw)
To: git; +Cc: Nicolas Pitre, Shawn O. Pearce, Jeff King
In addition to four basic types (commit, tree, blob and tag), the pack
stream can encode a few other "representation" types, such as REF_DELTA
and OFS_DELTA. As we allocate 3 bits in the first byte for this purpose,
we do not have much room to add new representation types in place, but we
do have one value reserved for future expansion.
This patch is about defining how that reserved value is used.
The first byte in the pack stream data consists of the following for the
current representation types:
- Bit 0-3 are used for the low 4-bit of "some" size (not necessarily the
size of the representation);
- Bit 4-6 are used for object types 0-7, but we have not used type 5 so
far and reserved it for future expansion (we could also use type 0
recorded in the pack stream for future expansion, just like how I
convert 5 into the real "extended" representation type in this patch);
- Bit 7 is used to signal if the second byte needs to be read for sizes
that do not fit in the 4-bit.
When bit 4-6 encodes type 5, the first byte is used this way:
- Bit 0-3 denotes the real "extended" representation type. Because types
0-7 can already be encoded without using the extended format, we can
offset the type by 8 (i.e. if bit 0-3 says 3, it means representation
type 11 = 3 + 8);
- Bit 4-6 has the value "5";
- Bit 7 is used to signal if the _third_ byte needs to be read for larger
size that cannot be represented with 8-bit.
As it is unlikely for us to pack things that do not need to record any
size, the second byte is always used in full to encode the low 8-bit of
the size.
I haven't started using type=8 and upwards for anything yet, but because
we have only one "future expansion" value left, I want us to be extremely
careful in order to avoid painting us into a corner that we cannot get out
of, so I am sending this out early for a preliminary review.
Signed-off-by: Junio C Hamano <gitster@pobox.com>
---
cache.h | 3 ++-
sha1_file.c | 36 ++++++++++++++++++++++++++++++++----
2 files changed, 34 insertions(+), 5 deletions(-)
diff --git a/cache.h b/cache.h
index 2e6ad36..b02139b 100644
--- a/cache.h
+++ b/cache.h
@@ -380,9 +380,10 @@ enum object_type {
OBJ_TREE = 2,
OBJ_BLOB = 3,
OBJ_TAG = 4,
- /* 5 for future expansion */
+ OBJ_EXT = 5, /* 5 for future expansion */
OBJ_OFS_DELTA = 6,
OBJ_REF_DELTA = 7,
+ OBJ_CAT_TREE = 8,
OBJ_ANY,
OBJ_MAX
};
diff --git a/sha1_file.c b/sha1_file.c
index 27f3b9b..4dcd023 100644
--- a/sha1_file.c
+++ b/sha1_file.c
@@ -1254,16 +1254,43 @@ static int experimental_loose_object(unsigned char *map)
}
unsigned long unpack_object_header_buffer(const unsigned char *buf,
- unsigned long len, enum object_type *type, unsigned long *sizep)
+ unsigned long len, enum object_type *typep, unsigned long *sizep)
{
unsigned shift;
unsigned long size, c;
unsigned long used = 0;
+ enum object_type type;
+ /*
+ * MSB of the first byte is used to tell if the second byte
+ * needs to be read for the size, so type field is only 3-bit
+ * wide.
+ */
c = buf[used++];
- *type = (c >> 4) & 7;
- size = c & 15;
- shift = 4;
+ type = (c >> 4) & 7;
+
+ if (type != OBJ_EXT) {
+ /*
+ * For basic types of object representations, the low
+ * 4-bit of the first byte is used for the lowermost
+ * 4-bit of the size. The MSB of the first byte tells
+ * if the second byte needs to be read for size.
+ */
+ size = c & 15;
+ shift = 4;
+ } else {
+ /*
+ * For extended types, the low 4-bit of the first byte
+ * is used for the representation type (offset by 8),
+ * and the size begins at the second byte. The MSB of
+ * the first byte is still used to indicate the next
+ * byte (i.e. the third byte) needs to be read for the
+ * size.
+ */
+ type = (c & 15) + 8;
+ size = buf[used++];
+ shift = 8;
+ }
while (c & 0x80) {
if (len <= used || bitsizeof(long) <= shift) {
error("bad object header");
@@ -1274,6 +1301,7 @@ unsigned long unpack_object_header_buffer(const unsigned char *buf,
shift += 7;
}
*sizep = size;
+ *typep = type;
return used;
}
^ permalink raw reply related
* Re: [PATCHv2 3/3] completion: match ctags symbol names in grep patterns
From: Jeff King @ 2011-10-28 6:05 UTC (permalink / raw)
To: SZEDER Gábor; +Cc: git
In-Reply-To: <20111023212928.GG22551@goldbirke>
On Sun, Oct 23, 2011 at 11:29:28PM +0200, SZEDER Gábor wrote:
> On Fri, Oct 21, 2011 at 01:30:21PM -0400, Jeff King wrote:
> > This incorporates the suggestions from Gábor's review, with one
> > exception: it still looks only in the current directory for the "tags"
> > files. I think that might have some performance implications, so I'd
> > rather add it separately, if at all.
>
> I agree that scanning through a whole working tree for tags files
> would cost too much. But I think that a tags file at the top of the
> working tree is common enough to be supported, and checking its
> existence is fairly cheap.
Actually, it's not too expensive. Asking git for the top of the working
tree means it has to traverse up to there anyway. So the trick is just
doing our search without invoking too many external tools which would
cause unnecessary forks.
The patch is below, but I'm still not sure it's a good idea.
Grep only looks in the current subdirectory for matches. So if I am in
"src/foo/bar/", and the tags file is in "src/", then is it really a good
way to generate completions? Most of what's in the tags file will
probably be in _other_ subdirectories of "src/", and won't be matched by
grep at all. So we will give useless entries to bash to complete.
> So how about something like this for the case arm? (I didn't actually
> tested it.)
>
> local tagsfile
> if test -r tags; then
> tagsfile=tags
> else
> local dir="$(__gitdir)"
You don't want __gitdir here, but rather "git rev-parse --show-cdup".
> Btw, there is a bug in the case statement: 'git --no-pager grep <TAB>'
> offers refs instead of symbols, because $cword is not 2 and $prev
> doesn't start with a dash. But it's not worse than the current
> behavior, so I don't think this bug is a show-stopper for the patch.
Yeah. The intent of the "$cword is 2" thing is to know that we are the
first non-option argument. Arguably, _get_comp_words_by_ref should
somehow tell us which position we are completing relative to the actual
command name.
-Peff
---
diff --git a/contrib/completion/git-completion.bash b/contrib/completion/git-completion.bash
index af283cb..b0ed657 100755
--- a/contrib/completion/git-completion.bash
+++ b/contrib/completion/git-completion.bash
@@ -1429,6 +1429,39 @@ _git_gitk ()
_gitk
}
+__git_cdup_dirs() {
+ local prefix=$(git rev-parse --show-cdup 2>/dev/null)
+ local oldifs=$IFS
+ local dots
+ local i
+ IFS=/
+ for i in $prefix; do
+ dots=$dots../
+ echo "$dots"
+ done
+ IFS=$oldifs
+}
+
+__git_find_in_cdup_one() {
+ local dir=$1; shift
+ for i in "$@"; do
+ if test -r "$dir$i"; then
+ echo "$dir$i"
+ return 0
+ fi
+ done
+ return 1
+}
+
+__git_find_in_cdup() {
+ __git_find_in_cdup_one "" "$@" && return
+
+ local dir
+ for dir in $(__git_cdup_dirs); do
+ __git_find_in_cdup_one "$dir" "$@" && return
+ done
+}
+
__git_match_ctag() {
awk "/^${1////\\/}/ { print \$1 }" "$2"
}
@@ -1457,8 +1490,9 @@ _git_grep ()
case "$cword,$prev" in
2,*|*,-*)
- if test -r tags; then
- __gitcomp "$(__git_match_ctag "$cur" tags)"
+ local tags=$(__git_find_in_cdup tags)
+ if test -n "$tags"; then
+ __gitcomp "$(__git_match_ctag "$cur" "$tags")"
return
fi
;;
^ permalink raw reply related
* Re: [RFC/PATCH] define the way new representation types are encoded in the pack
From: Junio C Hamano @ 2011-10-28 6:12 UTC (permalink / raw)
To: git; +Cc: Nicolas Pitre, Shawn O. Pearce, Jeff King
In-Reply-To: <7v62j9veh3.fsf@alter.siamese.dyndns.org>
Junio C Hamano <gitster@pobox.com> writes:
> I haven't started using type=8 and upwards for anything yet, but because
> we have only one "future expansion" value left, I want us to be extremely
> careful in order to avoid painting us into a corner that we cannot get out
> of, so I am sending this out early for a preliminary review.
>
> Signed-off-by: Junio C Hamano <gitster@pobox.com>
> ---
> cache.h | 3 ++-
> sha1_file.c | 36 ++++++++++++++++++++++++++++++++----
> 2 files changed, 34 insertions(+), 5 deletions(-)
>
> diff --git a/cache.h b/cache.h
> index 2e6ad36..b02139b 100644
> --- a/cache.h
> +++ b/cache.h
> @@ -380,9 +380,10 @@ enum object_type {
> OBJ_TREE = 2,
> OBJ_BLOB = 3,
> OBJ_TAG = 4,
> - /* 5 for future expansion */
> + OBJ_EXT = 5, /* 5 for future expansion */
> OBJ_OFS_DELTA = 6,
> OBJ_REF_DELTA = 7,
> + OBJ_CAT_TREE = 8,
> OBJ_ANY,
> OBJ_MAX
> };
As people may be able to guess from the name, CAT_TREE is envisioned to
encode a large data (primarily of type "blob") by recording the object
name of a tree object and probably the total length, and would represent
the concatenation of all blobs contained in the tree object when the tree
is traversed in some fixed order (e.g. Avery's "bup split"). I am guessing
that the payload for CAT_TREE representation type will be:
- 20-byte object name for the top-level tree object;
- type of the basic object (commit, tree, blob, or tag) it represents,
even though it is unlikely that we would want to record such a large
commit or tag that needs CAT_TREE representation;
- the total length of the basic object it represents, even though it is
redundant (you could traverse and sum the sizes of blobs contained in
the tree object), it would help sha1_object_info() and friends. This
will be the "some size" I mentioned in the previous message for this
representation type.
We would probably add loose object representation for CAT_TREE, which may
look like:
"cattree" <size of this cat-tree in decimal> NUL
<basic object type> <size of the basic object> NUL
<object name of the top-level tree>
and would need to teach unpack_sha1_file() about it. One caveat is that
we would want to keep the "contents name the object" invariant, so even if
a large blob is expressed as a CAT_TREE, its object name must still be
what we would get by hashing '"blob" <size> NUL <payload>'.
A loose object file in "cattree" representation will not hash to the value
a naïve implementation would expect, and fsck_sha1() needs to be aware of
it. I haven't thought things through in this area.
Further work would involve (no way exhaustive, of course):
- Teach fsck and connectivity tools that objects that are reachable from
any object (even a blob) that is represented as a CAT_TREE are needed
and reachable by that object;
- Teach pack-objects that anything that is represented as a CAT_TREE does
not need to be deltified (the objects used as its representation would
go through the usual deltification rules);
- Teach unpack-objects to expand CAT_TREE representation into a "cattree"
loose object.
- Perhaps teach the attributes mechanism to lie to anybody who asks that
any object in CAT_TREE representation is a binary file to trigger the
"we do not unnecessarily look at binary" logic in "git diff" machinery.
- Teach fast-import to write out CAT_TREE representation. This is
probably the quickest and least-impact way to exploit existing support
for large files in index_fd().
- Update grep.c::grep_buffer() to take not <buf,size> but git_istream,
and rewrite builtin/grep.c::grep_sha1() to use streaming interface.
^ permalink raw reply
* git rebase -p does not find mainline
From: David Kastrup @ 2011-10-28 7:51 UTC (permalink / raw)
To: git
When doing git rebase -p in order to do a non-trivial rebase tracking
merges, I get a message about a missing -m option for specifying the
mainline.
git rebase does not have the corresponding option. The fix is to do
git cherry-pick -m 1 offending-merge-commit
git rebase --continue
but that is quite unobvious from the resulting error message that does
not even mention "cherry-pick". Since git rebase -p is supposed to
"preserve merges", it should just cherry-pick with the same mainline
that the original merge commit had, without asking the user questions or
even failing.
This is the version of git delivered with Ubuntu 11.10, namely 1.7.5.4.
--
David Kastrup
^ permalink raw reply
* Re: git alias and --help
From: Michael J Gruber @ 2011-10-28 9:00 UTC (permalink / raw)
To: Junio C Hamano; +Cc: Miles Bader, Gelonida N, git
In-Reply-To: <7vvcr9wyje.fsf@alter.siamese.dyndns.org>
Junio C Hamano venit, vidit, dixit 28.10.2011 06:05:
> Miles Bader <miles@gnu.org> writes:
>
>> Of course, that would be the wrong thing for somebody that just wants
>> to be reminded what an alias expands too, but my intuition is that
>> this is a very tiny minority compared to people that want to examine
>> the options for the underlying command...
>
> And it is doubly wrong if help backend is configured to be anything but
> manpages, no?
>
> As I said, you should be able to come up with a patch that detects and
> special cases the no frills case (replacement to single token) to get what
> you want.
But "help" is still too much to type for the OP ;) How about this in
your config:
[alias]
h = help
hh = "!sh -c 'a=$(git config --get alias.$1); : ${a:=$1}; git help
${a%% *}' -"
Ugly as hell, I know, and works only for aliases whose first word is the
name of a git command, as well as for non-aliases. Catching "!command"
type aliases is left as an exercise to the reader.
Michael
^ permalink raw reply
* Re: [PATCH 2/2] pack-objects: optimize "recency order"
From: Ævar Arnfjörð Bjarmason @ 2011-10-28 9:17 UTC (permalink / raw)
To: Junio C Hamano; +Cc: git, Shawn O. Pearce, Dan McGee
In-Reply-To: <7vy5w6xf7n.fsf@alter.siamese.dyndns.org>
On Fri, Oct 28, 2011 at 00:05, Junio C Hamano <gitster@pobox.com> wrote:
> Ævar Arnfjörð Bjarmason <avarab@gmail.com> writes:
>
>> We recently upgraded to 1.7.7 and I've traced a very large slowdown in
>> packing down to this commit.
>
> Does Dan McGee's series leading to 38d4deb (pack-objects: don't traverse
> objects unnecessarily, 2011-10-18) help?
Yes it does!
When I do:
git cherry-pick 703f05ad5835cff92b12c29aecf8d724c8c847e2..38d4deb
Here's the time on the linux-2.6.git repack with that series:
real 0m53.969s
user 0m47.063s
sys 0m3.020s
On the repository I was having troubles with this was the result on
master:
Total 911023 (delta 687744), reused 905500 (delta 683064)
real 6m0.487s
user 4m1.751s
sys 1m56.331s
And with the cherry-pick:
Total 911023 (delta 687744), reused 911023 (delta 687744)
real 1m44.192s
user 0m32.169s
sys 0m4.383s
And with 1b4bb16b9ec331c91e28d2e3e7dee5070534b6a2 reverted:
Total 911023 (delta 687744), reused 911023 (delta 687744)
real 1m23.796s
user 0m31.931s
sys 0m3.549s
So it's still slower, but not intolerably slower. I'd be interested to
find out why we have that 20% difference that doesn't show up on
linux-2.6.git though, the repository is mostly source code but there
are some binary blobs in it as well, although not very large, the
overall size of the entire repository is <500MB.
^ permalink raw reply
* Re: git alias and --help
From: Gelonida N @ 2011-10-28 9:17 UTC (permalink / raw)
To: git
In-Reply-To: <7vvcr9wyje.fsf@alter.siamese.dyndns.org>
On 10/28/2011 06:05 AM, Junio C Hamano wrote:
> Miles Bader <miles@gnu.org> writes:
>
>> Of course, that would be the wrong thing for somebody that just wants
>> to be reminded what an alias expands too, but my intuition is that
>> this is a very tiny minority compared to people that want to examine
>> the options for the underlying command...
>
> And it is doubly wrong if help backend is configured to be anything but
> manpages, no?
Well. Then it is already doubly wrong today, isnt it?
The output of 'git help b'
is not a man page I assume.
In my opinion chaning it to a short message + the output of a man page
is not really worse than today's behaviour.
>
> As I said, you should be able to come up with a patch that detects and
> special cases the no frills case (replacement to single token) to get what
> you want.
That's perhaps the most comfortable one, though occasionally I am even
interested in the help text of a git command if I had an alias like
l = log --name-status
to see what other switches I could add
(Thus an alternative suggestion to display both or to have a special
syntax allowing to force displaying of a man page)
Another small detail:
Let's assume I have following alias:
log = log --name-status
In this case I directly get the help text for git log
if I typed 'git log --help' (or 'git help log').
I don't even see, that my log is in reality aliased.
^ permalink raw reply
* [PATCH v3 00/14] Tidying up references code
From: mhagger @ 2011-10-28 11:14 UTC (permalink / raw)
To: Junio C Hamano
Cc: git, Jeff King, Drew Northup, Jakub Narebski, Heiko Voigt,
Johan Herland, Julian Phillips, Michael Haggerty
From: Michael Haggerty <mhagger@alum.mit.edu>
I have re-rolled this patch series against gitster/master for your
merging enjoyment.
Original description of patch series:
This is the next installment of the reference changes that I have been
working on. This batch includes a lot of tidying up in preparation
for the real changes.
The last few patches have a little bit of meat on them. They start
changing the innards of refs.c to work less with strings and more with
objects. This work will continue in later patches with the ultimate
goal of swapping the data structure used to store cached references
out from under the module--changing it from a sorted array of pointers
into a hierarchical tree shaped like the reference namespace tree.
Michael Haggerty (14):
cache.h: add comments for git_path() and git_path_submodule()
struct ref_entry: document name member
refs: rename "refname" variables
refs: rename parameters result -> sha1
clear_ref_array(): rename from free_ref_array()
is_refname_available(): remove the "quiet" argument
parse_ref_line(): add docstring
add_ref(): add docstring
is_dup_ref(): extract function from sort_ref_array()
refs: change signatures of get_packed_refs() and get_loose_refs()
get_ref_dir(): change signature
resolve_gitlink_ref(): improve docstring
Pass a (ref_cache *) to the resolve_gitlink_*() helper functions
resolve_gitlink_ref_recursive(): change to work with struct ref_cache
cache.h | 18 +++
refs.c | 434 +++++++++++++++++++++++++++++++++------------------------------
refs.h | 34 +++--
3 files changed, 266 insertions(+), 220 deletions(-)
--
1.7.7
^ permalink raw reply
* [PATCH v3 07/14] parse_ref_line(): add docstring
From: mhagger @ 2011-10-28 11:14 UTC (permalink / raw)
To: Junio C Hamano
Cc: git, Jeff King, Drew Northup, Jakub Narebski, Heiko Voigt,
Johan Herland, Julian Phillips, Michael Haggerty
In-Reply-To: <1319800481-15138-1-git-send-email-mhagger@alum.mit.edu>
From: Michael Haggerty <mhagger@alum.mit.edu>
Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu>
---
refs.c | 5 +++++
1 files changed, 5 insertions(+), 0 deletions(-)
diff --git a/refs.c b/refs.c
index d3dcb3c..963291f 100644
--- a/refs.c
+++ b/refs.c
@@ -20,6 +20,11 @@ struct ref_array {
struct ref_entry **refs;
};
+/*
+ * Parse one line from a packed-refs file. Write the SHA1 to sha1.
+ * Return a pointer to the refname within the line (null-terminated),
+ * or NULL if there was a problem.
+ */
static const char *parse_ref_line(char *line, unsigned char *sha1)
{
/*
--
1.7.7
^ permalink raw reply related
* [PATCH v3 03/14] refs: rename "refname" variables
From: mhagger @ 2011-10-28 11:14 UTC (permalink / raw)
To: Junio C Hamano
Cc: git, Jeff King, Drew Northup, Jakub Narebski, Heiko Voigt,
Johan Herland, Julian Phillips, Michael Haggerty
In-Reply-To: <1319800481-15138-1-git-send-email-mhagger@alum.mit.edu>
From: Michael Haggerty <mhagger@alum.mit.edu>
Try to consistently use the variable name "refname" when referring to
a string that names a reference.
Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu>
---
refs.c | 276 +++++++++++++++++++++++++++++++++-------------------------------
refs.h | 26 ++++---
2 files changed, 157 insertions(+), 145 deletions(-)
diff --git a/refs.c b/refs.c
index 5fa880b..7a34e4b 100644
--- a/refs.c
+++ b/refs.c
@@ -48,7 +48,7 @@ static const char *parse_ref_line(char *line, unsigned char *sha1)
return line;
}
-static void add_ref(const char *name, const unsigned char *sha1,
+static void add_ref(const char *refname, const unsigned char *sha1,
int flag, struct ref_array *refs,
struct ref_entry **new_entry)
{
@@ -56,13 +56,13 @@ static void add_ref(const char *name, const unsigned char *sha1,
struct ref_entry *entry;
/* Allocate it and add it in.. */
- len = strlen(name) + 1;
+ len = strlen(refname) + 1;
entry = xmalloc(sizeof(struct ref_entry) + len);
hashcpy(entry->sha1, sha1);
hashclr(entry->peeled);
- if (check_refname_format(name, REFNAME_ALLOW_ONELEVEL|REFNAME_DOT_COMPONENT))
- die("Reference has invalid format: '%s'", name);
- memcpy(entry->name, name, len);
+ if (check_refname_format(refname, REFNAME_ALLOW_ONELEVEL|REFNAME_DOT_COMPONENT))
+ die("Reference has invalid format: '%s'", refname);
+ memcpy(entry->name, refname, len);
entry->flag = flag;
if (new_entry)
*new_entry = entry;
@@ -105,20 +105,20 @@ static void sort_ref_array(struct ref_array *array)
array->nr = i + 1;
}
-static struct ref_entry *search_ref_array(struct ref_array *array, const char *name)
+static struct ref_entry *search_ref_array(struct ref_array *array, const char *refname)
{
struct ref_entry *e, **r;
int len;
- if (name == NULL)
+ if (refname == NULL)
return NULL;
if (!array->nr)
return NULL;
- len = strlen(name) + 1;
+ len = strlen(refname) + 1;
e = xmalloc(sizeof(struct ref_entry) + len);
- memcpy(e->name, name, len);
+ memcpy(e->name, refname, len);
r = bsearch(&e, array->refs, array->nr, sizeof(*array->refs), ref_entry_cmp);
@@ -222,7 +222,7 @@ static void read_packed_refs(FILE *f, struct ref_array *array)
while (fgets(refline, sizeof(refline), f)) {
unsigned char sha1[20];
- const char *name;
+ const char *refname;
static const char header[] = "# pack-refs with:";
if (!strncmp(refline, header, sizeof(header)-1)) {
@@ -233,9 +233,9 @@ static void read_packed_refs(FILE *f, struct ref_array *array)
continue;
}
- name = parse_ref_line(refline, sha1);
- if (name) {
- add_ref(name, sha1, flag, array, &last);
+ refname = parse_ref_line(refline, sha1);
+ if (refname) {
+ add_ref(refname, sha1, flag, array, &last);
continue;
}
if (last &&
@@ -248,9 +248,9 @@ static void read_packed_refs(FILE *f, struct ref_array *array)
sort_ref_array(array);
}
-void add_extra_ref(const char *name, const unsigned char *sha1, int flag)
+void add_extra_ref(const char *refname, const unsigned char *sha1, int flag)
{
- add_ref(name, sha1, flag, &extra_refs, NULL);
+ add_ref(refname, sha1, flag, &extra_refs, NULL);
}
void clear_extra_refs(void)
@@ -401,7 +401,8 @@ static struct ref_array *get_loose_refs(const char *submodule)
* from "name", which is "module/.git/<refname>". Find <refname> in
* the packed-refs file for the submodule.
*/
-static int resolve_gitlink_packed_ref(char *name, int pathlen, const char *refname, unsigned char *result)
+static int resolve_gitlink_packed_ref(char *name, int pathlen,
+ const char *refname, unsigned char *result)
{
int retval = -1;
struct ref_entry *ref;
@@ -420,7 +421,9 @@ static int resolve_gitlink_packed_ref(char *name, int pathlen, const char *refna
return retval;
}
-static int resolve_gitlink_ref_recursive(char *name, int pathlen, const char *refname, unsigned char *result, int recursion)
+static int resolve_gitlink_ref_recursive(char *name, int pathlen,
+ const char *refname, unsigned char *result,
+ int recursion)
{
int fd, len = strlen(refname);
char buffer[128], *p;
@@ -487,10 +490,10 @@ int resolve_gitlink_ref(const char *path, const char *refname, unsigned char *re
* Try to read ref from the packed references. On success, set sha1
* and return 0; otherwise, return -1.
*/
-static int get_packed_ref(const char *ref, unsigned char *sha1)
+static int get_packed_ref(const char *refname, unsigned char *sha1)
{
struct ref_array *packed = get_packed_refs(NULL);
- struct ref_entry *entry = search_ref_array(packed, ref);
+ struct ref_entry *entry = search_ref_array(packed, refname);
if (entry) {
hashcpy(sha1, entry->sha1);
return 0;
@@ -498,17 +501,17 @@ static int get_packed_ref(const char *ref, unsigned char *sha1)
return -1;
}
-const char *resolve_ref(const char *ref, unsigned char *sha1, int reading, int *flag)
+const char *resolve_ref(const char *refname, unsigned char *sha1, int reading, int *flag)
{
int depth = MAXDEPTH;
ssize_t len;
char buffer[256];
- static char ref_buffer[256];
+ static char refname_buffer[256];
if (flag)
*flag = 0;
- if (check_refname_format(ref, REFNAME_ALLOW_ONELEVEL))
+ if (check_refname_format(refname, REFNAME_ALLOW_ONELEVEL))
return NULL;
for (;;) {
@@ -520,7 +523,7 @@ const char *resolve_ref(const char *ref, unsigned char *sha1, int reading, int *
if (--depth < 0)
return NULL;
- git_snpath(path, sizeof(path), "%s", ref);
+ git_snpath(path, sizeof(path), "%s", refname);
if (lstat(path, &st) < 0) {
if (errno != ENOENT)
@@ -529,17 +532,17 @@ const char *resolve_ref(const char *ref, unsigned char *sha1, int reading, int *
* The loose reference file does not exist;
* check for a packed reference.
*/
- if (!get_packed_ref(ref, sha1)) {
+ if (!get_packed_ref(refname, sha1)) {
if (flag)
*flag |= REF_ISPACKED;
- return ref;
+ return refname;
}
/* The reference is not a packed reference, either. */
if (reading) {
return NULL;
} else {
hashclr(sha1);
- return ref;
+ return refname;
}
}
@@ -551,8 +554,8 @@ const char *resolve_ref(const char *ref, unsigned char *sha1, int reading, int *
buffer[len] = 0;
if (!prefixcmp(buffer, "refs/") &&
!check_refname_format(buffer, 0)) {
- strcpy(ref_buffer, buffer);
- ref = ref_buffer;
+ strcpy(refname_buffer, buffer);
+ refname = refname_buffer;
if (flag)
*flag |= REF_ISSYMREF;
continue;
@@ -595,7 +598,7 @@ const char *resolve_ref(const char *ref, unsigned char *sha1, int reading, int *
*flag |= REF_ISBROKEN;
return NULL;
}
- ref = strcpy(ref_buffer, buf);
+ refname = strcpy(refname_buffer, buf);
}
/* Please note that FETCH_HEAD has a second line containing other data. */
if (get_sha1_hex(buffer, sha1) || (buffer[40] != '\0' && !isspace(buffer[40]))) {
@@ -603,7 +606,7 @@ const char *resolve_ref(const char *ref, unsigned char *sha1, int reading, int *
*flag |= REF_ISBROKEN;
return NULL;
}
- return ref;
+ return refname;
}
/* The argument to filter_refs */
@@ -613,9 +616,9 @@ struct ref_filter {
void *cb_data;
};
-int read_ref(const char *ref, unsigned char *sha1)
+int read_ref(const char *refname, unsigned char *sha1)
{
- if (resolve_ref(ref, sha1, 1, NULL))
+ if (resolve_ref(refname, sha1, 1, NULL))
return 0;
return -1;
}
@@ -639,23 +642,23 @@ static int do_one_ref(const char *base, each_ref_fn fn, int trim,
return fn(entry->name + trim, entry->sha1, entry->flag, cb_data);
}
-static int filter_refs(const char *ref, const unsigned char *sha, int flags,
+static int filter_refs(const char *refname, const unsigned char *sha, int flags,
void *data)
{
struct ref_filter *filter = (struct ref_filter *)data;
- if (fnmatch(filter->pattern, ref, 0))
+ if (fnmatch(filter->pattern, refname, 0))
return 0;
- return filter->fn(ref, sha, flags, filter->cb_data);
+ return filter->fn(refname, sha, flags, filter->cb_data);
}
-int peel_ref(const char *ref, unsigned char *sha1)
+int peel_ref(const char *refname, unsigned char *sha1)
{
int flag;
unsigned char base[20];
struct object *o;
- if (current_ref && (current_ref->name == ref
- || !strcmp(current_ref->name, ref))) {
+ if (current_ref && (current_ref->name == refname
+ || !strcmp(current_ref->name, refname))) {
if (current_ref->flag & REF_KNOWS_PEELED) {
hashcpy(sha1, current_ref->peeled);
return 0;
@@ -664,12 +667,12 @@ int peel_ref(const char *ref, unsigned char *sha1)
goto fallback;
}
- if (!resolve_ref(ref, base, 1, &flag))
+ if (!resolve_ref(refname, base, 1, &flag))
return -1;
if ((flag & REF_ISPACKED)) {
struct ref_array *array = get_packed_refs(NULL);
- struct ref_entry *r = search_ref_array(array, ref);
+ struct ref_entry *r = search_ref_array(array, refname);
if (r != NULL && r->flag & REF_KNOWS_PEELED) {
hashcpy(sha1, r->peeled);
@@ -680,7 +683,7 @@ int peel_ref(const char *ref, unsigned char *sha1)
fallback:
o = parse_object(base);
if (o && o->type == OBJ_TAG) {
- o = deref_tag(o, ref, 0);
+ o = deref_tag(o, refname, 0);
if (o) {
hashcpy(sha1, o->sha1);
return 0;
@@ -910,16 +913,16 @@ static inline int bad_ref_char(int ch)
}
/*
- * Try to read one refname component from the front of ref. Return
+ * Try to read one refname component from the front of refname. Return
* the length of the component found, or -1 if the component is not
* legal.
*/
-static int check_refname_component(const char *ref, int flags)
+static int check_refname_component(const char *refname, int flags)
{
const char *cp;
char last = '\0';
- for (cp = ref; ; cp++) {
+ for (cp = refname; ; cp++) {
char ch = *cp;
if (ch == '\0' || ch == '/')
break;
@@ -931,34 +934,34 @@ static int check_refname_component(const char *ref, int flags)
return -1; /* Refname contains "@{". */
last = ch;
}
- if (cp == ref)
+ if (cp == refname)
return -1; /* Component has zero length. */
- if (ref[0] == '.') {
+ if (refname[0] == '.') {
if (!(flags & REFNAME_DOT_COMPONENT))
return -1; /* Component starts with '.'. */
/*
* Even if leading dots are allowed, don't allow "."
* as a component (".." is prevented by a rule above).
*/
- if (ref[1] == '\0')
+ if (refname[1] == '\0')
return -1; /* Component equals ".". */
}
- if (cp - ref >= 5 && !memcmp(cp - 5, ".lock", 5))
+ if (cp - refname >= 5 && !memcmp(cp - 5, ".lock", 5))
return -1; /* Refname ends with ".lock". */
- return cp - ref;
+ return cp - refname;
}
-int check_refname_format(const char *ref, int flags)
+int check_refname_format(const char *refname, int flags)
{
int component_len, component_count = 0;
while (1) {
/* We are at the start of a path component. */
- component_len = check_refname_component(ref, flags);
+ component_len = check_refname_component(refname, flags);
if (component_len < 0) {
if ((flags & REFNAME_REFSPEC_PATTERN) &&
- ref[0] == '*' &&
- (ref[1] == '\0' || ref[1] == '/')) {
+ refname[0] == '*' &&
+ (refname[1] == '\0' || refname[1] == '/')) {
/* Accept one wildcard as a full refname component. */
flags &= ~REFNAME_REFSPEC_PATTERN;
component_len = 1;
@@ -967,13 +970,13 @@ int check_refname_format(const char *ref, int flags)
}
}
component_count++;
- if (ref[component_len] == '\0')
+ if (refname[component_len] == '\0')
break;
/* Skip to next component. */
- ref += component_len + 1;
+ refname += component_len + 1;
}
- if (ref[component_len - 1] == '.')
+ if (refname[component_len - 1] == '.')
return -1; /* Refname ends with '.'. */
if (!(flags & REFNAME_ALLOW_ONELEVEL) && component_count < 2)
return -1; /* Refname has only one component. */
@@ -1056,22 +1059,22 @@ static int remove_empty_directories(const char *file)
return result;
}
-static int is_refname_available(const char *ref, const char *oldref,
+static int is_refname_available(const char *refname, const char *oldrefname,
struct ref_array *array, int quiet)
{
- int i, namlen = strlen(ref); /* e.g. 'foo/bar' */
+ int i, namlen = strlen(refname); /* e.g. 'foo/bar' */
for (i = 0; i < array->nr; i++ ) {
struct ref_entry *entry = array->refs[i];
/* entry->name could be 'foo' or 'foo/bar/baz' */
- if (!oldref || strcmp(oldref, entry->name)) {
+ if (!oldrefname || strcmp(oldrefname, entry->name)) {
int len = strlen(entry->name);
int cmplen = (namlen < len) ? namlen : len;
- const char *lead = (namlen < len) ? entry->name : ref;
- if (!strncmp(ref, entry->name, cmplen) &&
+ const char *lead = (namlen < len) ? entry->name : refname;
+ if (!strncmp(refname, entry->name, cmplen) &&
lead[cmplen] == '/') {
if (!quiet)
error("'%s' exists; cannot create '%s'",
- entry->name, ref);
+ entry->name, refname);
return 0;
}
}
@@ -1167,10 +1170,12 @@ int dwim_log(const char *str, int len, unsigned char *sha1, char **log)
return logs_found;
}
-static struct ref_lock *lock_ref_sha1_basic(const char *ref, const unsigned char *old_sha1, int flags, int *type_p)
+static struct ref_lock *lock_ref_sha1_basic(const char *refname,
+ const unsigned char *old_sha1,
+ int flags, int *type_p)
{
char *ref_file;
- const char *orig_ref = ref;
+ const char *orig_refname = refname;
struct ref_lock *lock;
int last_errno = 0;
int type, lflags;
@@ -1180,27 +1185,27 @@ static struct ref_lock *lock_ref_sha1_basic(const char *ref, const unsigned char
lock = xcalloc(1, sizeof(struct ref_lock));
lock->lock_fd = -1;
- ref = resolve_ref(ref, lock->old_sha1, mustexist, &type);
- if (!ref && errno == EISDIR) {
+ refname = resolve_ref(refname, lock->old_sha1, mustexist, &type);
+ if (!refname && errno == EISDIR) {
/* we are trying to lock foo but we used to
* have foo/bar which now does not exist;
* it is normal for the empty directory 'foo'
* to remain.
*/
- ref_file = git_path("%s", orig_ref);
+ ref_file = git_path("%s", orig_refname);
if (remove_empty_directories(ref_file)) {
last_errno = errno;
- error("there are still refs under '%s'", orig_ref);
+ error("there are still refs under '%s'", orig_refname);
goto error_return;
}
- ref = resolve_ref(orig_ref, lock->old_sha1, mustexist, &type);
+ refname = resolve_ref(orig_refname, lock->old_sha1, mustexist, &type);
}
if (type_p)
*type_p = type;
- if (!ref) {
+ if (!refname) {
last_errno = errno;
error("unable to resolve reference %s: %s",
- orig_ref, strerror(errno));
+ orig_refname, strerror(errno));
goto error_return;
}
missing = is_null_sha1(lock->old_sha1);
@@ -1210,7 +1215,7 @@ static struct ref_lock *lock_ref_sha1_basic(const char *ref, const unsigned char
* name is a proper prefix of our refname.
*/
if (missing &&
- !is_refname_available(ref, NULL, get_packed_refs(NULL), 0)) {
+ !is_refname_available(refname, NULL, get_packed_refs(NULL), 0)) {
last_errno = ENOTDIR;
goto error_return;
}
@@ -1219,12 +1224,12 @@ static struct ref_lock *lock_ref_sha1_basic(const char *ref, const unsigned char
lflags = LOCK_DIE_ON_ERROR;
if (flags & REF_NODEREF) {
- ref = orig_ref;
+ refname = orig_refname;
lflags |= LOCK_NODEREF;
}
- lock->ref_name = xstrdup(ref);
- lock->orig_ref_name = xstrdup(orig_ref);
- ref_file = git_path("%s", ref);
+ lock->ref_name = xstrdup(refname);
+ lock->orig_ref_name = xstrdup(orig_refname);
+ ref_file = git_path("%s", refname);
if (missing)
lock->force_write = 1;
if ((flags & REF_NODEREF) && (type & REF_ISSYMREF))
@@ -1245,20 +1250,21 @@ static struct ref_lock *lock_ref_sha1_basic(const char *ref, const unsigned char
return NULL;
}
-struct ref_lock *lock_ref_sha1(const char *ref, const unsigned char *old_sha1)
+struct ref_lock *lock_ref_sha1(const char *refname, const unsigned char *old_sha1)
{
char refpath[PATH_MAX];
- if (check_refname_format(ref, 0))
+ if (check_refname_format(refname, 0))
return NULL;
- strcpy(refpath, mkpath("refs/%s", ref));
+ strcpy(refpath, mkpath("refs/%s", refname));
return lock_ref_sha1_basic(refpath, old_sha1, 0, NULL);
}
-struct ref_lock *lock_any_ref_for_update(const char *ref, const unsigned char *old_sha1, int flags)
+struct ref_lock *lock_any_ref_for_update(const char *refname,
+ const unsigned char *old_sha1, int flags)
{
- if (check_refname_format(ref, REFNAME_ALLOW_ONELEVEL))
+ if (check_refname_format(refname, REFNAME_ALLOW_ONELEVEL))
return NULL;
- return lock_ref_sha1_basic(ref, old_sha1, flags, NULL);
+ return lock_ref_sha1_basic(refname, old_sha1, flags, NULL);
}
static struct lock_file packlock;
@@ -1344,96 +1350,96 @@ int delete_ref(const char *refname, const unsigned char *sha1, int delopt)
*/
#define TMP_RENAMED_LOG "logs/refs/.tmp-renamed-log"
-int rename_ref(const char *oldref, const char *newref, const char *logmsg)
+int rename_ref(const char *oldrefname, const char *newrefname, const char *logmsg)
{
unsigned char sha1[20], orig_sha1[20];
int flag = 0, logmoved = 0;
struct ref_lock *lock;
struct stat loginfo;
- int log = !lstat(git_path("logs/%s", oldref), &loginfo);
+ int log = !lstat(git_path("logs/%s", oldrefname), &loginfo);
const char *symref = NULL;
if (log && S_ISLNK(loginfo.st_mode))
- return error("reflog for %s is a symlink", oldref);
+ return error("reflog for %s is a symlink", oldrefname);
- symref = resolve_ref(oldref, orig_sha1, 1, &flag);
+ symref = resolve_ref(oldrefname, orig_sha1, 1, &flag);
if (flag & REF_ISSYMREF)
return error("refname %s is a symbolic ref, renaming it is not supported",
- oldref);
+ oldrefname);
if (!symref)
- return error("refname %s not found", oldref);
+ return error("refname %s not found", oldrefname);
- if (!is_refname_available(newref, oldref, get_packed_refs(NULL), 0))
+ if (!is_refname_available(newrefname, oldrefname, get_packed_refs(NULL), 0))
return 1;
- if (!is_refname_available(newref, oldref, get_loose_refs(NULL), 0))
+ if (!is_refname_available(newrefname, oldrefname, get_loose_refs(NULL), 0))
return 1;
- if (log && rename(git_path("logs/%s", oldref), git_path(TMP_RENAMED_LOG)))
+ if (log && rename(git_path("logs/%s", oldrefname), git_path(TMP_RENAMED_LOG)))
return error("unable to move logfile logs/%s to "TMP_RENAMED_LOG": %s",
- oldref, strerror(errno));
+ oldrefname, strerror(errno));
- if (delete_ref(oldref, orig_sha1, REF_NODEREF)) {
- error("unable to delete old %s", oldref);
+ if (delete_ref(oldrefname, orig_sha1, REF_NODEREF)) {
+ error("unable to delete old %s", oldrefname);
goto rollback;
}
- if (resolve_ref(newref, sha1, 1, &flag) && delete_ref(newref, sha1, REF_NODEREF)) {
+ if (resolve_ref(newrefname, sha1, 1, &flag) && delete_ref(newrefname, sha1, REF_NODEREF)) {
if (errno==EISDIR) {
- if (remove_empty_directories(git_path("%s", newref))) {
- error("Directory not empty: %s", newref);
+ if (remove_empty_directories(git_path("%s", newrefname))) {
+ error("Directory not empty: %s", newrefname);
goto rollback;
}
} else {
- error("unable to delete existing %s", newref);
+ error("unable to delete existing %s", newrefname);
goto rollback;
}
}
- if (log && safe_create_leading_directories(git_path("logs/%s", newref))) {
- error("unable to create directory for %s", newref);
+ if (log && safe_create_leading_directories(git_path("logs/%s", newrefname))) {
+ error("unable to create directory for %s", newrefname);
goto rollback;
}
retry:
- if (log && rename(git_path(TMP_RENAMED_LOG), git_path("logs/%s", newref))) {
+ if (log && rename(git_path(TMP_RENAMED_LOG), git_path("logs/%s", newrefname))) {
if (errno==EISDIR || errno==ENOTDIR) {
/*
* rename(a, b) when b is an existing
* directory ought to result in ISDIR, but
* Solaris 5.8 gives ENOTDIR. Sheesh.
*/
- if (remove_empty_directories(git_path("logs/%s", newref))) {
- error("Directory not empty: logs/%s", newref);
+ if (remove_empty_directories(git_path("logs/%s", newrefname))) {
+ error("Directory not empty: logs/%s", newrefname);
goto rollback;
}
goto retry;
} else {
error("unable to move logfile "TMP_RENAMED_LOG" to logs/%s: %s",
- newref, strerror(errno));
+ newrefname, strerror(errno));
goto rollback;
}
}
logmoved = log;
- lock = lock_ref_sha1_basic(newref, NULL, 0, NULL);
+ lock = lock_ref_sha1_basic(newrefname, NULL, 0, NULL);
if (!lock) {
- error("unable to lock %s for update", newref);
+ error("unable to lock %s for update", newrefname);
goto rollback;
}
lock->force_write = 1;
hashcpy(lock->old_sha1, orig_sha1);
if (write_ref_sha1(lock, orig_sha1, logmsg)) {
- error("unable to write current sha1 into %s", newref);
+ error("unable to write current sha1 into %s", newrefname);
goto rollback;
}
return 0;
rollback:
- lock = lock_ref_sha1_basic(oldref, NULL, 0, NULL);
+ lock = lock_ref_sha1_basic(oldrefname, NULL, 0, NULL);
if (!lock) {
- error("unable to lock %s for rollback", oldref);
+ error("unable to lock %s for rollback", oldrefname);
goto rollbacklog;
}
@@ -1441,17 +1447,17 @@ int rename_ref(const char *oldref, const char *newref, const char *logmsg)
flag = log_all_ref_updates;
log_all_ref_updates = 0;
if (write_ref_sha1(lock, orig_sha1, NULL))
- error("unable to write current sha1 into %s", oldref);
+ error("unable to write current sha1 into %s", oldrefname);
log_all_ref_updates = flag;
rollbacklog:
- if (logmoved && rename(git_path("logs/%s", newref), git_path("logs/%s", oldref)))
+ if (logmoved && rename(git_path("logs/%s", newrefname), git_path("logs/%s", oldrefname)))
error("unable to restore logfile %s from %s: %s",
- oldref, newref, strerror(errno));
+ oldrefname, newrefname, strerror(errno));
if (!logmoved && log &&
- rename(git_path(TMP_RENAMED_LOG), git_path("logs/%s", oldref)))
+ rename(git_path(TMP_RENAMED_LOG), git_path("logs/%s", oldrefname)))
error("unable to restore logfile %s from "TMP_RENAMED_LOG": %s",
- oldref, strerror(errno));
+ oldrefname, strerror(errno));
return 1;
}
@@ -1508,16 +1514,16 @@ static int copy_msg(char *buf, const char *msg)
return cp - buf;
}
-int log_ref_setup(const char *ref_name, char *logfile, int bufsize)
+int log_ref_setup(const char *refname, char *logfile, int bufsize)
{
int logfd, oflags = O_APPEND | O_WRONLY;
- git_snpath(logfile, bufsize, "logs/%s", ref_name);
+ git_snpath(logfile, bufsize, "logs/%s", refname);
if (log_all_ref_updates &&
- (!prefixcmp(ref_name, "refs/heads/") ||
- !prefixcmp(ref_name, "refs/remotes/") ||
- !prefixcmp(ref_name, "refs/notes/") ||
- !strcmp(ref_name, "HEAD"))) {
+ (!prefixcmp(refname, "refs/heads/") ||
+ !prefixcmp(refname, "refs/remotes/") ||
+ !prefixcmp(refname, "refs/notes/") ||
+ !strcmp(refname, "HEAD"))) {
if (safe_create_leading_directories(logfile) < 0)
return error("unable to create directory for %s",
logfile);
@@ -1547,7 +1553,7 @@ int log_ref_setup(const char *ref_name, char *logfile, int bufsize)
return 0;
}
-static int log_ref_write(const char *ref_name, const unsigned char *old_sha1,
+static int log_ref_write(const char *refname, const unsigned char *old_sha1,
const unsigned char *new_sha1, const char *msg)
{
int logfd, result, written, oflags = O_APPEND | O_WRONLY;
@@ -1560,7 +1566,7 @@ static int log_ref_write(const char *ref_name, const unsigned char *old_sha1,
if (log_all_ref_updates < 0)
log_all_ref_updates = !is_bare_repository();
- result = log_ref_setup(ref_name, log_file, sizeof(log_file));
+ result = log_ref_setup(refname, log_file, sizeof(log_file));
if (result)
return result;
@@ -1731,7 +1737,9 @@ static char *ref_msg(const char *line, const char *endp)
return xmemdupz(line, ep - line);
}
-int read_ref_at(const char *ref, unsigned long at_time, int cnt, unsigned char *sha1, char **msg, unsigned long *cutoff_time, int *cutoff_tz, int *cutoff_cnt)
+int read_ref_at(const char *refname, unsigned long at_time, int cnt,
+ unsigned char *sha1, char **msg,
+ unsigned long *cutoff_time, int *cutoff_tz, int *cutoff_cnt)
{
const char *logfile, *logdata, *logend, *rec, *lastgt, *lastrec;
char *tz_c;
@@ -1742,7 +1750,7 @@ int read_ref_at(const char *ref, unsigned long at_time, int cnt, unsigned char *
void *log_mapped;
size_t mapsz;
- logfile = git_path("logs/%s", ref);
+ logfile = git_path("logs/%s", refname);
logfd = open(logfile, O_RDONLY, 0);
if (logfd < 0)
die_errno("Unable to read log '%s'", logfile);
@@ -1835,14 +1843,14 @@ int read_ref_at(const char *ref, unsigned long at_time, int cnt, unsigned char *
return 1;
}
-int for_each_recent_reflog_ent(const char *ref, each_reflog_ent_fn fn, long ofs, void *cb_data)
+int for_each_recent_reflog_ent(const char *refname, each_reflog_ent_fn fn, long ofs, void *cb_data)
{
const char *logfile;
FILE *logfp;
struct strbuf sb = STRBUF_INIT;
int ret = 0;
- logfile = git_path("logs/%s", ref);
+ logfile = git_path("logs/%s", refname);
logfp = fopen(logfile, "r");
if (!logfp)
return -1;
@@ -1893,9 +1901,9 @@ int for_each_recent_reflog_ent(const char *ref, each_reflog_ent_fn fn, long ofs,
return ret;
}
-int for_each_reflog_ent(const char *ref, each_reflog_ent_fn fn, void *cb_data)
+int for_each_reflog_ent(const char *refname, each_reflog_ent_fn fn, void *cb_data)
{
- return for_each_recent_reflog_ent(ref, fn, 0, cb_data);
+ return for_each_recent_reflog_ent(refname, fn, 0, cb_data);
}
static int do_for_each_reflog(const char *base, each_ref_fn fn, void *cb_data)
@@ -2015,7 +2023,7 @@ static void gen_scanf_fmt(char *scanf_fmt, const char *rule)
return;
}
-char *shorten_unambiguous_ref(const char *ref, int strict)
+char *shorten_unambiguous_ref(const char *refname, int strict)
{
int i;
static char **scanf_fmts;
@@ -2044,10 +2052,10 @@ char *shorten_unambiguous_ref(const char *ref, int strict)
/* bail out if there are no rules */
if (!nr_rules)
- return xstrdup(ref);
+ return xstrdup(refname);
- /* buffer for scanf result, at most ref must fit */
- short_name = xstrdup(ref);
+ /* buffer for scanf result, at most refname must fit */
+ short_name = xstrdup(refname);
/* skip first rule, it will always match */
for (i = nr_rules - 1; i > 0 ; --i) {
@@ -2055,7 +2063,7 @@ char *shorten_unambiguous_ref(const char *ref, int strict)
int rules_to_fail = i;
int short_name_len;
- if (1 != sscanf(ref, scanf_fmts[i], short_name))
+ if (1 != sscanf(refname, scanf_fmts[i], short_name))
continue;
short_name_len = strlen(short_name);
@@ -2100,5 +2108,5 @@ char *shorten_unambiguous_ref(const char *ref, int strict)
}
free(short_name);
- return xstrdup(ref);
+ return xstrdup(refname);
}
diff --git a/refs.h b/refs.h
index 3fd5536..e36bd03 100644
--- a/refs.h
+++ b/refs.h
@@ -60,14 +60,16 @@ extern void add_extra_ref(const char *refname, const unsigned char *sha1, int fl
extern void clear_extra_refs(void);
extern int ref_exists(const char *);
-extern int peel_ref(const char *, unsigned char *);
+extern int peel_ref(const char *refname, unsigned char *sha1);
/** Locks a "refs/" ref returning the lock on success and NULL on failure. **/
-extern struct ref_lock *lock_ref_sha1(const char *ref, const unsigned char *old_sha1);
+extern struct ref_lock *lock_ref_sha1(const char *refname, const unsigned char *old_sha1);
/** Locks any ref (for 'HEAD' type refs). */
#define REF_NODEREF 0x01
-extern struct ref_lock *lock_any_ref_for_update(const char *ref, const unsigned char *old_sha1, int flags);
+extern struct ref_lock *lock_any_ref_for_update(const char *refname,
+ const unsigned char *old_sha1,
+ int flags);
/** Close the file descriptor owned by a lock and return the status */
extern int close_ref(struct ref_lock *lock);
@@ -93,12 +95,14 @@ extern void invalidate_ref_cache(const char *submodule);
int log_ref_setup(const char *ref_name, char *logfile, int bufsize);
/** Reads log for the value of ref during at_time. **/
-extern int read_ref_at(const char *ref, unsigned long at_time, int cnt, unsigned char *sha1, char **msg, unsigned long *cutoff_time, int *cutoff_tz, int *cutoff_cnt);
+extern int read_ref_at(const char *refname, unsigned long at_time, int cnt,
+ unsigned char *sha1, char **msg,
+ unsigned long *cutoff_time, int *cutoff_tz, int *cutoff_cnt);
/* iterate over reflog entries */
typedef int each_reflog_ent_fn(unsigned char *osha1, unsigned char *nsha1, const char *, unsigned long, int, const char *, void *);
-int for_each_reflog_ent(const char *ref, each_reflog_ent_fn fn, void *cb_data);
-int for_each_recent_reflog_ent(const char *ref, each_reflog_ent_fn fn, long, void *cb_data);
+int for_each_reflog_ent(const char *refname, each_reflog_ent_fn fn, void *cb_data);
+int for_each_recent_reflog_ent(const char *refname, each_reflog_ent_fn fn, long, void *cb_data);
/*
* Calls the specified function for each reflog file until it returns nonzero,
@@ -111,9 +115,9 @@ extern int for_each_reflog(each_ref_fn, void *);
#define REFNAME_DOT_COMPONENT 4
/*
- * Return 0 iff ref has the correct format for a refname according to
- * the rules described in Documentation/git-check-ref-format.txt. If
- * REFNAME_ALLOW_ONELEVEL is set in flags, then accept one-level
+ * Return 0 iff refname has the correct format for a refname according
+ * to the rules described in Documentation/git-check-ref-format.txt.
+ * If REFNAME_ALLOW_ONELEVEL is set in flags, then accept one-level
* reference names. If REFNAME_REFSPEC_PATTERN is set in flags, then
* allow a "*" wildcard character in place of one of the name
* components. No leading or repeated slashes are accepted. If
@@ -121,10 +125,10 @@ extern int for_each_reflog(each_ref_fn, void *);
* components to start with "." (but not a whole component equal to
* "." or "..").
*/
-extern int check_refname_format(const char *ref, int flags);
+extern int check_refname_format(const char *refname, int flags);
extern const char *prettify_refname(const char *refname);
-extern char *shorten_unambiguous_ref(const char *ref, int strict);
+extern char *shorten_unambiguous_ref(const char *refname, int strict);
/** rename ref, return 0 on success **/
extern int rename_ref(const char *oldref, const char *newref, const char *logmsg);
--
1.7.7
^ permalink raw reply related
* [PATCH v3 06/14] is_refname_available(): remove the "quiet" argument
From: mhagger @ 2011-10-28 11:14 UTC (permalink / raw)
To: Junio C Hamano
Cc: git, Jeff King, Drew Northup, Jakub Narebski, Heiko Voigt,
Johan Herland, Julian Phillips, Michael Haggerty
In-Reply-To: <1319800481-15138-1-git-send-email-mhagger@alum.mit.edu>
From: Michael Haggerty <mhagger@alum.mit.edu>
quiet was always set to 0, so get rid of it. Add a function docstring
for good measure.
Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu>
---
refs.c | 20 +++++++++++++-------
1 files changed, 13 insertions(+), 7 deletions(-)
diff --git a/refs.c b/refs.c
index c9e14fd..d3dcb3c 100644
--- a/refs.c
+++ b/refs.c
@@ -1059,8 +1059,15 @@ static int remove_empty_directories(const char *file)
return result;
}
+/*
+ * Return true iff a reference named refname could be created without
+ * conflicting with the name of an existing reference. If oldrefname
+ * is non-NULL, ignore potential conflicts with oldrefname (e.g.,
+ * because oldrefname is scheduled for deletion in the same
+ * operation).
+ */
static int is_refname_available(const char *refname, const char *oldrefname,
- struct ref_array *array, int quiet)
+ struct ref_array *array)
{
int i, namlen = strlen(refname); /* e.g. 'foo/bar' */
for (i = 0; i < array->nr; i++ ) {
@@ -1072,9 +1079,8 @@ static int is_refname_available(const char *refname, const char *oldrefname,
const char *lead = (namlen < len) ? entry->name : refname;
if (!strncmp(refname, entry->name, cmplen) &&
lead[cmplen] == '/') {
- if (!quiet)
- error("'%s' exists; cannot create '%s'",
- entry->name, refname);
+ error("'%s' exists; cannot create '%s'",
+ entry->name, refname);
return 0;
}
}
@@ -1215,7 +1221,7 @@ static struct ref_lock *lock_ref_sha1_basic(const char *refname,
* name is a proper prefix of our refname.
*/
if (missing &&
- !is_refname_available(refname, NULL, get_packed_refs(NULL), 0)) {
+ !is_refname_available(refname, NULL, get_packed_refs(NULL))) {
last_errno = ENOTDIR;
goto error_return;
}
@@ -1369,10 +1375,10 @@ int rename_ref(const char *oldrefname, const char *newrefname, const char *logms
if (!symref)
return error("refname %s not found", oldrefname);
- if (!is_refname_available(newrefname, oldrefname, get_packed_refs(NULL), 0))
+ if (!is_refname_available(newrefname, oldrefname, get_packed_refs(NULL)))
return 1;
- if (!is_refname_available(newrefname, oldrefname, get_loose_refs(NULL), 0))
+ if (!is_refname_available(newrefname, oldrefname, get_loose_refs(NULL)))
return 1;
if (log && rename(git_path("logs/%s", oldrefname), git_path(TMP_RENAMED_LOG)))
--
1.7.7
^ permalink raw reply related
* [PATCH v3 02/14] struct ref_entry: document name member
From: mhagger @ 2011-10-28 11:14 UTC (permalink / raw)
To: Junio C Hamano
Cc: git, Jeff King, Drew Northup, Jakub Narebski, Heiko Voigt,
Johan Herland, Julian Phillips, Michael Haggerty
In-Reply-To: <1319800481-15138-1-git-send-email-mhagger@alum.mit.edu>
From: Michael Haggerty <mhagger@alum.mit.edu>
Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu>
---
refs.c | 1 +
1 files changed, 1 insertions(+), 0 deletions(-)
diff --git a/refs.c b/refs.c
index e69ba26..5fa880b 100644
--- a/refs.c
+++ b/refs.c
@@ -11,6 +11,7 @@ struct ref_entry {
unsigned char flag; /* ISSYMREF? ISPACKED? */
unsigned char sha1[20];
unsigned char peeled[20];
+ /* The full name of the reference (e.g., "refs/heads/master"): */
char name[FLEX_ARRAY];
};
--
1.7.7
^ permalink raw reply related
* [PATCH v3 01/14] cache.h: add comments for git_path() and git_path_submodule()
From: mhagger @ 2011-10-28 11:14 UTC (permalink / raw)
To: Junio C Hamano
Cc: git, Jeff King, Drew Northup, Jakub Narebski, Heiko Voigt,
Johan Herland, Julian Phillips, Michael Haggerty
In-Reply-To: <1319800481-15138-1-git-send-email-mhagger@alum.mit.edu>
From: Michael Haggerty <mhagger@alum.mit.edu>
Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu>
---
cache.h | 18 ++++++++++++++++++
1 files changed, 18 insertions(+), 0 deletions(-)
diff --git a/cache.h b/cache.h
index 2e6ad36..5e807b9 100644
--- a/cache.h
+++ b/cache.h
@@ -662,7 +662,25 @@ extern char *git_pathdup(const char *fmt, ...)
/* Return a statically allocated filename matching the sha1 signature */
extern char *mkpath(const char *fmt, ...) __attribute__((format (printf, 1, 2)));
+
+/*
+ * Return the path of a file within get_git_dir(). The arguments
+ * should be printf-like arguments that produce the filename relative
+ * to get_git_dir(). Return the resulting path, or "/bad-path/" if
+ * there is an error. The return value is a pointer into a temporary
+ * buffer that will be overwritten without notice.
+ */
extern char *git_path(const char *fmt, ...) __attribute__((format (printf, 1, 2)));
+
+/*
+ * Return the path of a file within the git_dir of the submodule
+ * located at path. The other arguments should be printf-like
+ * arguments that produce the filename relative to "<path>/.git". If
+ * "<path>/.git" is a gitlink file, follow it to find the actual
+ * submodule git_dir. Return the resulting path, or "/bad-path/" if
+ * there is an error. The return value is a pointer into a temporary
+ * buffer that will be overwritten without notice.
+ */
extern char *git_path_submodule(const char *path, const char *fmt, ...)
__attribute__((format (printf, 2, 3)));
--
1.7.7
^ permalink raw reply related
* [PATCH v3 05/14] clear_ref_array(): rename from free_ref_array()
From: mhagger @ 2011-10-28 11:14 UTC (permalink / raw)
To: Junio C Hamano
Cc: git, Jeff King, Drew Northup, Jakub Narebski, Heiko Voigt,
Johan Herland, Julian Phillips, Michael Haggerty
In-Reply-To: <1319800481-15138-1-git-send-email-mhagger@alum.mit.edu>
From: Michael Haggerty <mhagger@alum.mit.edu>
Rename the function since it doesn't actually free the array object
that is passed to it.
Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu>
---
refs.c | 8 ++++----
1 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/refs.c b/refs.c
index 564070c..c9e14fd 100644
--- a/refs.c
+++ b/refs.c
@@ -148,7 +148,7 @@ static struct ref_entry *current_ref;
static struct ref_array extra_refs;
-static void free_ref_array(struct ref_array *array)
+static void clear_ref_array(struct ref_array *array)
{
int i;
for (i = 0; i < array->nr; i++)
@@ -161,14 +161,14 @@ static void free_ref_array(struct ref_array *array)
static void clear_packed_ref_cache(struct ref_cache *refs)
{
if (refs->did_packed)
- free_ref_array(&refs->packed);
+ clear_ref_array(&refs->packed);
refs->did_packed = 0;
}
static void clear_loose_ref_cache(struct ref_cache *refs)
{
if (refs->did_loose)
- free_ref_array(&refs->loose);
+ clear_ref_array(&refs->loose);
refs->did_loose = 0;
}
@@ -255,7 +255,7 @@ void add_extra_ref(const char *refname, const unsigned char *sha1, int flag)
void clear_extra_refs(void)
{
- free_ref_array(&extra_refs);
+ clear_ref_array(&extra_refs);
}
static struct ref_array *get_packed_refs(const char *submodule)
--
1.7.7
^ permalink raw reply related
* [PATCH v3 09/14] is_dup_ref(): extract function from sort_ref_array()
From: mhagger @ 2011-10-28 11:14 UTC (permalink / raw)
To: Junio C Hamano
Cc: git, Jeff King, Drew Northup, Jakub Narebski, Heiko Voigt,
Johan Herland, Julian Phillips, Michael Haggerty
In-Reply-To: <1319800481-15138-1-git-send-email-mhagger@alum.mit.edu>
From: Michael Haggerty <mhagger@alum.mit.edu>
Giving it a name makes the code easier to understand. And the new
function will be convenient later when it has to be called from
multiple places.
Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu>
---
refs.c | 25 ++++++++++++++++++++-----
1 files changed, 20 insertions(+), 5 deletions(-)
diff --git a/refs.c b/refs.c
index a94af1d..50fc567 100644
--- a/refs.c
+++ b/refs.c
@@ -83,6 +83,25 @@ static int ref_entry_cmp(const void *a, const void *b)
return strcmp(one->name, two->name);
}
+/*
+ * Emit a warning and return true iff ref1 and ref2 have the same name
+ * and the same sha1. Die if they have the same name but different
+ * sha1s.
+ */
+static int is_dup_ref(const struct ref_entry *ref1, const struct ref_entry *ref2)
+{
+ if (!strcmp(ref1->name, ref2->name)) {
+ /* Duplicate name; make sure that the SHA1s match: */
+ if (hashcmp(ref1->sha1, ref2->sha1))
+ die("Duplicated ref, and SHA1s don't match: %s",
+ ref1->name);
+ warning("Duplicated ref: %s", ref1->name);
+ return 1;
+ } else {
+ return 0;
+ }
+}
+
static void sort_ref_array(struct ref_array *array)
{
int i = 0, j = 1;
@@ -97,11 +116,7 @@ static void sort_ref_array(struct ref_array *array)
for (; j < array->nr; j++) {
struct ref_entry *a = array->refs[i];
struct ref_entry *b = array->refs[j];
- if (!strcmp(a->name, b->name)) {
- if (hashcmp(a->sha1, b->sha1))
- die("Duplicated ref, and SHA1s don't match: %s",
- a->name);
- warning("Duplicated ref: %s", a->name);
+ if (is_dup_ref(a, b)) {
free(b);
continue;
}
--
1.7.7
^ permalink raw reply related
* [PATCH v3 04/14] refs: rename parameters result -> sha1
From: mhagger @ 2011-10-28 11:14 UTC (permalink / raw)
To: Junio C Hamano
Cc: git, Jeff King, Drew Northup, Jakub Narebski, Heiko Voigt,
Johan Herland, Julian Phillips, Michael Haggerty
In-Reply-To: <1319800481-15138-1-git-send-email-mhagger@alum.mit.edu>
From: Michael Haggerty <mhagger@alum.mit.edu>
Try consistently to use the name "sha1" for parameters to which a SHA1
will be stored.
Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu>
---
refs.c | 16 ++++++++--------
refs.h | 2 +-
2 files changed, 9 insertions(+), 9 deletions(-)
diff --git a/refs.c b/refs.c
index 7a34e4b..564070c 100644
--- a/refs.c
+++ b/refs.c
@@ -402,7 +402,7 @@ static struct ref_array *get_loose_refs(const char *submodule)
* the packed-refs file for the submodule.
*/
static int resolve_gitlink_packed_ref(char *name, int pathlen,
- const char *refname, unsigned char *result)
+ const char *refname, unsigned char *sha1)
{
int retval = -1;
struct ref_entry *ref;
@@ -415,14 +415,14 @@ static int resolve_gitlink_packed_ref(char *name, int pathlen,
array = get_packed_refs(name);
ref = search_ref_array(array, refname);
if (ref != NULL) {
- memcpy(result, ref->sha1, 20);
+ memcpy(sha1, ref->sha1, 20);
retval = 0;
}
return retval;
}
static int resolve_gitlink_ref_recursive(char *name, int pathlen,
- const char *refname, unsigned char *result,
+ const char *refname, unsigned char *sha1,
int recursion)
{
int fd, len = strlen(refname);
@@ -433,7 +433,7 @@ static int resolve_gitlink_ref_recursive(char *name, int pathlen,
memcpy(name + pathlen, refname, len+1);
fd = open(name, O_RDONLY);
if (fd < 0)
- return resolve_gitlink_packed_ref(name, pathlen, refname, result);
+ return resolve_gitlink_packed_ref(name, pathlen, refname, sha1);
len = read(fd, buffer, sizeof(buffer)-1);
close(fd);
@@ -444,7 +444,7 @@ static int resolve_gitlink_ref_recursive(char *name, int pathlen,
buffer[len] = 0;
/* Was it a detached head or an old-fashioned symlink? */
- if (!get_sha1_hex(buffer, result))
+ if (!get_sha1_hex(buffer, sha1))
return 0;
/* Symref? */
@@ -454,10 +454,10 @@ static int resolve_gitlink_ref_recursive(char *name, int pathlen,
while (isspace(*p))
p++;
- return resolve_gitlink_ref_recursive(name, pathlen, p, result, recursion+1);
+ return resolve_gitlink_ref_recursive(name, pathlen, p, sha1, recursion+1);
}
-int resolve_gitlink_ref(const char *path, const char *refname, unsigned char *result)
+int resolve_gitlink_ref(const char *path, const char *refname, unsigned char *sha1)
{
int len = strlen(path), retval;
char *gitdir;
@@ -481,7 +481,7 @@ int resolve_gitlink_ref(const char *path, const char *refname, unsigned char *re
}
gitdir[len] = '/';
gitdir[++len] = '\0';
- retval = resolve_gitlink_ref_recursive(gitdir, len, refname, result, 0);
+ retval = resolve_gitlink_ref_recursive(gitdir, len, refname, sha1, 0);
free(gitdir);
return retval;
}
diff --git a/refs.h b/refs.h
index e36bd03..4c5d570 100644
--- a/refs.h
+++ b/refs.h
@@ -134,7 +134,7 @@ extern char *shorten_unambiguous_ref(const char *refname, int strict);
extern int rename_ref(const char *oldref, const char *newref, const char *logmsg);
/** resolve ref in nested "gitlink" repository */
-extern int resolve_gitlink_ref(const char *name, const char *refname, unsigned char *result);
+extern int resolve_gitlink_ref(const char *name, const char *refname, unsigned char *sha1);
/** lock a ref and then write its file */
enum action_on_err { MSG_ON_ERR, DIE_ON_ERR, QUIET_ON_ERR };
--
1.7.7
^ permalink raw reply related
* [PATCH v3 08/14] add_ref(): add docstring
From: mhagger @ 2011-10-28 11:14 UTC (permalink / raw)
To: Junio C Hamano
Cc: git, Jeff King, Drew Northup, Jakub Narebski, Heiko Voigt,
Johan Herland, Julian Phillips, Michael Haggerty
In-Reply-To: <1319800481-15138-1-git-send-email-mhagger@alum.mit.edu>
From: Michael Haggerty <mhagger@alum.mit.edu>
Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu>
---
refs.c | 1 +
1 files changed, 1 insertions(+), 0 deletions(-)
diff --git a/refs.c b/refs.c
index 963291f..a94af1d 100644
--- a/refs.c
+++ b/refs.c
@@ -53,6 +53,7 @@ static const char *parse_ref_line(char *line, unsigned char *sha1)
return line;
}
+/* Add a ref_entry to the end of the ref_array (unsorted). */
static void add_ref(const char *refname, const unsigned char *sha1,
int flag, struct ref_array *refs,
struct ref_entry **new_entry)
--
1.7.7
^ 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