* Re: Implementing branch attributes in git config
From: Pavel Roskin @ 2006-05-08 0:36 UTC (permalink / raw)
To: Linus Torvalds; +Cc: git
In-Reply-To: <Pine.LNX.4.64.0605071629080.3718@g5.osdl.org>
Hello, Linus!
On Sun, 2006-05-07 at 17:05 -0700, Linus Torvalds wrote:
> The downside is that if you start using config files like this, you
> literally can't go back to older git versions. They'll refuse to touch
> such a config file (rather than just ignoring the new entries) and will
> exit with nasty messages. That might be unacceptable.
You code faster that I write e-mails :-)
I like your approach, even though it breaks compatibility. I understand
we are going to more .git/remotes to the config, so compatibility will
be broken anyways.
I'm only concerned that we would be hardcoding the word "branch". We
could need fancy section names for other things in the future.
--
Regards,
Pavel Roskin
^ permalink raw reply
* Re: Unresolved issues #2 (shallow clone again)
From: Theodore Tso @ 2006-05-08 0:33 UTC (permalink / raw)
To: git
In-Reply-To: <20060507075631.GA24423@coredump.intra.peff.net>
On Sun, May 07, 2006 at 03:56:31AM -0400, Jeff King wrote:
> On Sun, May 07, 2006 at 06:08:03PM +1200, Martin Langhoff wrote:
>
> > >> And in any case commits and trees are lightweight and compress well...
> > >Commit maybe, but is this based on a hard fact?
> > No hard facts here :( but I think it's reasonable to assume that the
> > trees delta/compress reasonably well, as a given commit will change
> > just a few entries in each tree.
>
> A few hard facts (using Linus' linux-2.6 tree):
> - original packsize: 120996 kilobytes
> - unpacked: 233338 objects, 1417476 kilobytes
> This is an 11.7:1 compression ratio (of course, much of this is
> wasted space from the 4k block size in the filesystem)
If there are 233338 objects, then the average wasted space due to
internal fragmentation is 233338 * 2k, or 466676 kilobytes, or only
36% of the wasted space. Most of the savings is probably coming from
the compression and delta packing.
- Ted
^ permalink raw reply
* Re: [PATCH] Release config lock if the regex is invalid
From: Johannes Schindelin @ 2006-05-08 0:32 UTC (permalink / raw)
To: Pavel Roskin; +Cc: git
In-Reply-To: <20060507213612.27887.28600.stgit@dv.roinet.com>
Hi,
On Sun, 7 May 2006, Pavel Roskin wrote:
> @@ -516,6 +516,8 @@ int git_config_set_multivar(const char*
> fprintf(stderr, "Invalid pattern: %s\n",
> value_regex);
> free(store.value_regex);
> + close(fd);
> + unlink(lock_file);
> ret = 6;
> goto out_free;
> }
>
This is not enough. There are quite a few exit paths. Notice the "goto
out_free"? That is where this must go.
This patch is totally untested but obviously correct:
diff --git a/config.c b/config.c
index 30effe3..d8fd94d 100644
--- a/config.c
+++ b/config.c
@@ -445,7 +445,7 @@ int git_config_set_multivar(const char*
const char* value_regex, int multi_replace)
{
int i;
- int fd;
+ int fd = -1;
int ret;
char* config_filename = strdup(git_path("config"));
char* lock_file = strdup(git_path("config.lock"));
@@ -619,10 +619,14 @@ int git_config_set_multivar(const char*
ret = 0;
out_free:
+ if (fd > 0)
+ close(fd);
if (config_filename)
free(config_filename);
- if (lock_file)
+ if (lock_file) {
+ unlink(lock_file);
free(lock_file);
+ }
return ret;
}
^ permalink raw reply related
* Re: Implementing branch attributes in git config
From: Linus Torvalds @ 2006-05-08 0:25 UTC (permalink / raw)
To: Pavel Roskin; +Cc: git
In-Reply-To: <Pine.LNX.4.64.0605071629080.3718@g5.osdl.org>
On Sun, 7 May 2006, Linus Torvalds wrote:
>
> The downside is that if you start using config files like this, you
> literally can't go back to older git versions. They'll refuse to touch
> such a config file (rather than just ignoring the new entries) and will
> exit with nasty messages. That might be unacceptable.
Side note: with this syntax, the _users_ will all just basically do
if (!strncmp(name, "branch.", 7)) {
branch = name + 7;
dot = strchr(branch, '.');
if (!dot)
return -1;
*dot++ = 0;
.. we now have the branchname in "branc",
and the rest in "dot" ..
and if your branch names are purely alphabetical and lower-case, you can
now write
[branch.origin]
remote = true
url = git://git.kernel.org/...
fetch = master
[branch.master]
pull = origin
and it will be parsed _exactly_ the same as
["origin"]
remote = true
url = git://git.kernel.org/...
fetch = master
["master"]
pull = origin
while the [branch.origin] syntax allows old versions of git to happily
ignore it. So that would be a kind of cheesy work-around: the new
double-quoted format is only _required_ for any branch-names that have
special characters in it.
Linus
^ permalink raw reply
* Re: Implementing branch attributes in git config
From: Linus Torvalds @ 2006-05-08 0:18 UTC (permalink / raw)
To: Pavel Roskin; +Cc: git
In-Reply-To: <Pine.LNX.4.64.0605071629080.3718@g5.osdl.org>
On Sun, 7 May 2006, Linus Torvalds wrote:
>
> And it's certainly simple enough.
Well, simple enough to be buggy.
> static int get_base_var(char *name)
> {
> int baselen = 0;
> + int c = get_next_char();
> +
> + if (c == '"')
> + return get_branch_name(name);
>
> for (;;) {
> int c = get_next_char();
You also need to move the "int c = get_next_char()" in the for() loop down
to the end of the loop (removing the "int", of course).
So here's the fixed thing in case people care (and this time I actually
looked at whether it might even work, not just compile ;)
Linus
---
diff --git a/config.c b/config.c
index 41066e4..69d451a 100644
--- a/config.c
+++ b/config.c
@@ -134,12 +134,46 @@ static int get_value(config_fn_t fn, cha
return fn(name, value);
}
+static int get_branch_name(char *name)
+{
+ int baselen = 7;
+ int quote = 0;
+
+ memcpy(name, "branch.", 7);
+ for (;;) {
+ int c = get_next_char();
+ if (c == EOF)
+ return -1;
+ if (c == '\n')
+ return -1;
+ if (!quote) {
+ if (c == '"')
+ break;
+ if (c == ']')
+ return -1;
+ if (c == '\\') {
+ quote = 1;
+ continue;
+ }
+ }
+ name[baselen++] = c;
+ if (baselen > MAXNAME / 2)
+ return -1;
+ }
+ if (get_next_char() != ']')
+ return -1;
+ return baselen;
+}
+
static int get_base_var(char *name)
{
int baselen = 0;
+ int c = get_next_char();
+
+ if (c == '"')
+ return get_branch_name(name);
for (;;) {
- int c = get_next_char();
if (c == EOF)
return -1;
if (c == ']')
@@ -149,6 +183,7 @@ static int get_base_var(char *name)
if (baselen > MAXNAME / 2)
return -1;
name[baselen++] = tolower(c);
+ c = get_next_char();
}
}
^ permalink raw reply related
* Re: Implementing branch attributes in git config
From: Linus Torvalds @ 2006-05-08 0:05 UTC (permalink / raw)
To: Pavel Roskin; +Cc: git
In-Reply-To: <1147037659.25090.25.camel@dv>
On Sun, 7 May 2006, Pavel Roskin wrote:
>
> I think a good implementation should allow any characters in the keys,
> even "=", because the key can be quoted. Section names may disallow
> square brackets and dots.
That wouldn't help. The thing is designed to not only need no quoting
(except for the _value_), it also is designed to have both section and key
names ignore case. So you really aren't supposed to put things like branch
names (which are potentially case-sensitive, depending on filesystem) in
either.
And we depend on that (and I think it's important - users normally should
_not_ care about capitalization)
So you'd need to literally create a different syntax if you want unquoted
section naming.
> Such limitations make it unpractical to use branch names in section or
> key names. I'd like to have it fixed.
Here's a possible syntax/patch. I actually think the quoting makes more
sense in the section name, since you'll usually want several keys under
each branch, so it makes sense to make the _branch_ be the section.
It basically makes it a special case if you have the section name be
marked with quotes, like
["XyZZy"]
and in that case it turns the _real_ section name into the string
"branch.XyZZy", where the important part is that it does this without
changing case or limiting the character set (but it will _not_ allow a
newline) in any way.
So you could have something like
["Origin"]
URL = ...
fetch = master
and it would just turn it into
branch.Origin.url = ...
branch.Origin.fetch = master
etc.
No, I'm not sure this is the best possible syntax. It's just a suggestion.
And it's certainly simple enough.
The downside is that if you start using config files like this, you
literally can't go back to older git versions. They'll refuse to touch
such a config file (rather than just ignoring the new entries) and will
exit with nasty messages. That might be unacceptable.
Instead of quoting with double-quotes, it might be ok to use some
alternate syntax line "[:$branchname:]" which looks visually reasonable,
and has the potential advantage that ':' is already an invalid character
in a branch name, so you don't actually even need any quoting logic at all
at that point.
I think the
["branch"]
...
syntax looks reasonably readable and clean.
Linus
----
diff --git a/config.c b/config.c
index 41066e4..802e326 100644
--- a/config.c
+++ b/config.c
@@ -134,9 +134,44 @@ static int get_value(config_fn_t fn, cha
return fn(name, value);
}
+static int get_branch_name(char *name)
+{
+ int baselen = 7;
+ int quote = 0;
+
+ memcpy(name, "branch.", 7);
+ for (;;) {
+ int c = get_next_char();
+ if (c == EOF)
+ return -1;
+ if (c == '\n')
+ return -1;
+ if (!quote) {
+ if (c == '"')
+ break;
+ if (c == ']')
+ return -1;
+ if (c == '\\') {
+ quote = 1;
+ continue;
+ }
+ }
+ name[baselen++] = c;
+ if (baselen > MAXNAME / 2)
+ return -1;
+ }
+ if (get_next_char() != ']')
+ return -1;
+ return baselen;
+}
+
static int get_base_var(char *name)
{
int baselen = 0;
+ int c = get_next_char();
+
+ if (c == '"')
+ return get_branch_name(name);
for (;;) {
int c = get_next_char();
^ permalink raw reply related
* Re: Unresolved issues #2 (shallow clone again)
From: Martin Langhoff @ 2006-05-07 23:44 UTC (permalink / raw)
To: Junio C Hamano; +Cc: git
In-Reply-To: <7vveshif1i.fsf@assigned-by-dhcp.cox.net>
On 5/8/06, Junio C Hamano <junkio@cox.net> wrote:
> It shouldn't. The existing packfile is designed to make "git
> log" very efficient, by making it cheap to look only at the
> commit message and ancestry information.
>
> The objects are sorted first by type in the pack with the
> existing code already, and commits come first. Try this.
Thanks for the explanation! My ignorance in the pre-coffee stage of
Monday is... exemplary. I should know better than assume that there
are trivial optimizations for git that I can come up with ;-)
I guess I should get more into the pack stuff and educate myself --
everyone's having fun with it... grumble, will have to brush up my C
to get to play.
cheers,
martin
^ permalink raw reply
* Re: [PATCH] Release config lock if the regex is invalid
From: Junio C Hamano @ 2006-05-07 23:37 UTC (permalink / raw)
To: Pavel Roskin; +Cc: git
In-Reply-To: <20060507213612.27887.28600.stgit@dv.roinet.com>
Thanks.
^ permalink raw reply
* Re: Unresolved issues #2 (shallow clone again)
From: Junio C Hamano @ 2006-05-07 23:35 UTC (permalink / raw)
To: Martin Langhoff; +Cc: git
In-Reply-To: <46a038f90605071627i6a335f61lf5e35291bfbe340c@mail.gmail.com>
"Martin Langhoff" <martin.langhoff@gmail.com> writes:
> On 5/7/06, Sergey Vlasov <vsu@altlinux.ru> wrote:
>> For linux v2.6.16:
>>
>> 7,3M commits-b41b04a36afebdba3b70b74f419fc7d97249bd7f.pack
>> 24M commits_trees-8397f1c2a885527acd07e2caa8c95df626451493.pack
>> 97M full-c7b2747a674ff55cb4a59dabebe419f191e360df.pack
>
> With this pack arrangement, do you get any noticeable difference in
> walking commits? How about walking commits+trees with git-log <path> ?
>
> I wonder whether segregating packs by object type would make things better...
It shouldn't. The existing packfile is designed to make "git
log" very efficient, by making it cheap to look only at the
commit message and ancestry information.
The objects are sorted first by type in the pack with the
existing code already, and commits come first. Try this.
git repack -a -d
git show-index <.git/objects/pack/pack-*.idx |
sort -n |
while read offset objectname
do
git cat-file -t "$objectname"
done
^ permalink raw reply
* Re: Unresolved issues #2 (shallow clone again)
From: Martin Langhoff @ 2006-05-07 23:27 UTC (permalink / raw)
To: Sergey Vlasov; +Cc: Junio C Hamano, git
In-Reply-To: <20060507120149.40e9f749.vsu@altlinux.ru>
On 5/7/06, Sergey Vlasov <vsu@altlinux.ru> wrote:
> For linux v2.6.16:
>
> 7,3M commits-b41b04a36afebdba3b70b74f419fc7d97249bd7f.pack
> 24M commits_trees-8397f1c2a885527acd07e2caa8c95df626451493.pack
> 97M full-c7b2747a674ff55cb4a59dabebe419f191e360df.pack
With this pack arrangement, do you get any noticeable difference in
walking commits? How about walking commits+trees with git-log <path> ?
I wonder whether segregating packs by object type would make things better...
cheers,
martin
^ permalink raw reply
* Re: Implementing branch attributes in git config
From: Junio C Hamano @ 2006-05-07 22:24 UTC (permalink / raw)
To: Pavel Roskin; +Cc: git
In-Reply-To: <1147037659.25090.25.camel@dv>
Pavel Roskin <proski@gnu.org> writes:
> In particular, git-repo-config leaves the config file locked in the
> regex is wrong:
>
> $ git-repo-config branch.fetch "master:origin" +
> Invalid pattern: +
> $ git-repo-config branch.fetch "master:origin" +
> could not lock config file
>
> To fix it, just add "close(fd); unlink(lock_file);" after "Invalid
> pattern" in config.c.
I'd give Johannes the first refusal right to deal with this and
not touch repo-config.c myself for now, since I suspect I
tempted him enough to restructure it ;-).
> I don't quite understand what pattern is needed to add an entry. "foo"
> seems to work fine, I don't know why.
I think the value regexp is "replace the ones that match this",
and the convention he came up with is to use "^$" to append (see
some examples in t/t1300-repo-config.sh).
In any case, Documentation/git-repo-config.txt mentions
value_regex without explaining what the semantics is. This
needs to be fixed, probably like the attached patch.
> That problem with multiple values is that they are quite fragile and
> require special options to access them. Since regex is used, dots in
> the branch names need to be escaped. Probably more escapes are needed.
I have a suspicion that using regex while is more powerful and
expressive might be a mistake and it would be easier for users
(both Porcelain and end-users) to use fnmatch() patterns.
> Such limitations make it unpractical to use branch names in section or
> key names. I'd like to have it fixed.
I thought that is what the "for blah" convention is for (BTW
"for" is not a keyword, just a convention).
Also the syntax is a bit confusing. I initially was confused,
after looking at your example:
[branch]
fetch = "localbranch:remotebranch"
that the colon separated value was a usual refspec, but it
isn't. The LHS is the name of the current branch, and RHS is
the name of the remotes/ file, which is not a remote _branch_ at
all. Perhaps something like this is semantically clearer, aside
from names -- I am bad at coming up with them:
[branch]
defaultremote = origin for master
defaultremote = private for test
to mean, "we use remotes/origin when on master branch by
default". Also we would want to use remote.origin.{url,fetch}
configuration item as well, so the "file existence" check you do
in this part of the patch is wrong.
> case "$#" in
> 0)
> - test -f "$GIT_DIR/branches/origin" ||
> - test -f "$GIT_DIR/remotes/origin" ||
> - die "Where do you want to fetch from today?"
> - set origin ;;
> + get_config_rem_branch
> + test -f "$GIT_DIR/branches/$fetch_branch" ||
> + test -f "$GIT_DIR/remotes/$fetch_branch" ||
> + die "No remote branch \"$fetch_branch\""
> + set "$fetch_branch" ;;
> esac
We should instead let the existence check do the right thing for
"$1" when it is used; after all the default "origin" may not
exist, and I suspect we do not probably check that (or if we do
already, the above check is totally unnecessary).
I haven't thought things through but I have a suspicion that
get_config_rem_branch might belong to git-parse-remote.sh not
git-fetch.sh.
-- >8 --
diff --git a/Documentation/git-repo-config.txt b/Documentation/git-repo-config.txt
index fd44f62..660c18f 100644
--- a/Documentation/git-repo-config.txt
+++ b/Documentation/git-repo-config.txt
@@ -23,10 +23,11 @@ You can query/set/replace/unset options
actually the section and the key separated by a dot, and the value will be
escaped.
-If you want to set/unset an option which can occur on multiple lines, you
-should provide a POSIX regex for the value. If you want to handle the lines
-*not* matching the regex, just prepend a single exclamation mark in front
-(see EXAMPLES).
+If you want to set/unset an option which can occur on multiple
+lines, a POSIX regexp `value_regex` needs to be given. Only the
+existing values that match the regexp are updated or unset. If
+you want to handle the lines that do *not* match the regex, just
+prepend a single exclamation mark in front (see EXAMPLES).
The type specifier can be either '--int' or '--bool', which will make
'git-repo-config' ensure that the variable(s) are of the given type and
^ permalink raw reply related
* [PATCH] Release config lock if the regex is invalid
From: Pavel Roskin @ 2006-05-07 21:36 UTC (permalink / raw)
To: git
Signed-off-by: Pavel Roskin <proski@gnu.org>
---
config.c | 2 ++
1 files changed, 2 insertions(+), 0 deletions(-)
diff --git a/config.c b/config.c
index 41066e4..61eacef 100644
--- a/config.c
+++ b/config.c
@@ -516,6 +516,8 @@ int git_config_set_multivar(const char*
fprintf(stderr, "Invalid pattern: %s\n",
value_regex);
free(store.value_regex);
+ close(fd);
+ unlink(lock_file);
ret = 6;
goto out_free;
}
^ permalink raw reply related
* Implementing branch attributes in git config
From: Pavel Roskin @ 2006-05-07 21:34 UTC (permalink / raw)
To: git
Hello!
I have tried to implement branch attributes (more specifically, the
default for git-fetch) in git config. It turns out that the format of
the config file is to rigid.
Minuses, underscores, colons and dots are not allowed in the section
headers and keys. I can understand that dots should be allowed either
in the section names or in the key names, but other limitations seem
totally unnecessary.
I think a good implementation should allow any characters in the keys,
even "=", because the key can be quoted. Section names may disallow
square brackets and dots.
Such limitations make it unpractical to use branch names in section or
key names. I'd like to have it fixed.
The only remaining place is values. This means that there should be
multiple entries for the same key. While this is allowed, it seems
quite fragile and inconvenient.
In particular, git-repo-config leaves the config file locked in the
regex is wrong:
$ git-repo-config branch.fetch "master:origin" +
Invalid pattern: +
$ git-repo-config branch.fetch "master:origin" +
could not lock config file
To fix it, just add "close(fd); unlink(lock_file);" after "Invalid
pattern" in config.c.
I don't quite understand what pattern is needed to add an entry. "foo"
seems to work fine, I don't know why.
That problem with multiple values is that they are quite fragile and
require special options to access them. Since regex is used, dots in
the branch names need to be escaped. Probably more escapes are needed.
Anyway, here's the preliminary patch that implements default fetch
branches. Unfortunately, it doesn't even come close to the goal of
having per-branch attributes due to the config file limitations.
To add an entry, use
git-repo-config branch.fetch "localbranch:remotebranch" foo
Read the default fetch branch from the config file
From: Pavel Roskin <proski@gnu.org>
---
git-fetch.sh | 21 +++++++++++++++++----
1 files changed, 17 insertions(+), 4 deletions(-)
diff --git a/git-fetch.sh b/git-fetch.sh
index 280f62e..a5ea92b 100755
--- a/git-fetch.sh
+++ b/git-fetch.sh
@@ -61,12 +61,25 @@ do
shift
done
+get_config_rem_branch() {
+ fetch_branch=origin
+ cur_branch=$(expr $(git-symbolic-ref HEAD) : 'refs/heads/\(.*\)')
+ test -z "$cur_branch" && return
+ cur_branch_esc=$(echo $cur_branch | sed 's/\./\\./')
+ branch_map=$(git-repo-config --get branch.fetch "^$cur_branch_esc:")
+ test -z "$branch_map" && return
+ rem_branch=$(expr "$branch_map" : "$cur_branch_esc:\(.*\)")
+ test -z "$rem_branch" && return
+ fetch_branch="$rem_branch"
+}
+
case "$#" in
0)
- test -f "$GIT_DIR/branches/origin" ||
- test -f "$GIT_DIR/remotes/origin" ||
- die "Where do you want to fetch from today?"
- set origin ;;
+ get_config_rem_branch
+ test -f "$GIT_DIR/branches/$fetch_branch" ||
+ test -f "$GIT_DIR/remotes/$fetch_branch" ||
+ die "No remote branch \"$fetch_branch\""
+ set "$fetch_branch" ;;
esac
remote_nick="$1"
--
Regards,
Pavel Roskin
^ permalink raw reply related
* Re: [patch] munmap-before-rename, cygwin need
From: Junio C Hamano @ 2006-05-07 21:14 UTC (permalink / raw)
To: Yakov Lerner; +Cc: git
In-Reply-To: <f36b08ee0605071258s7a0cb085r3f08e9981234255a@mail.gmail.com>
"Yakov Lerner" <iler.ml@gmail.com> writes:
> I found that mmap() works on cygwin, but needs a patch.
> On Cygwin, rename() fails if target file has active mmap().
> The patch below adds munmap() before rename().
This is interesting in three counts.
- I from time to time test Cygwin version on my day-job machine
(W2K) and my wife's machine (XP); on both machines I usually
have less than two weeks old Cygwin installation, and I have
not seen the breakage. I wonder how reproducible this is.
Also previously people reported mmap() works for some and
fake mmap is needed for others. Would this patch make things
work for everybody?
- The part you patched is commit_index_file(). This typically
is called just before program exit, but some callers, like
apply.c, may want to still look at the index after calling
it, fully aware that the changes after commit_index will not
be written out. Although I haven't traced the codepath fully
in apply.c yet, unmapping would break the access to the index
(i.e. active_cache[]). Does apply still work with your
patch?
- As long as you can clear the second point, I do not see a
particular reason to make this an option; we should be able
to do so everywhere.
^ permalink raw reply
* Re: [PATCH] Sparse fix for builtin-diff
From: Junio C Hamano @ 2006-05-07 20:43 UTC (permalink / raw)
To: Peter Hagervall; +Cc: junkio, git
In-Reply-To: <20060507145046.GA24882@peppar.cs.umu.se>
Peter Hagervall <hager@cs.umu.se> writes:
> You gotta love sparse:
>
> builtin-diff.c:88:4: error: Just how const do you want this type to be?
LOL.
> - const
> - const unsigned char *tmp_u;
> + const unsigned char *tmp_u;
I wondered how this bit snuck in, but it was like that
from the beginning, my bad.
Thanks.
^ permalink raw reply
* [patch] munmap-before-rename, cygwin need
From: Yakov Lerner @ 2006-05-07 19:58 UTC (permalink / raw)
To: git
[-- Attachment #1: Type: text/plain, Size: 2749 bytes --]
I found that mmap() works on cygwin, but needs a patch.
On Cygwin, rename() fails if target file has active mmap().
The patch below adds munmap() before rename().
If you excuse me for posting not in git-generated format
(I did not yet completely make git working on my cygwin).
I'm adding the copy as attachment, I'm afraid the mailer
may interfere with spaces ?
Yakov Lerner
Makefile | 5 +++++
cache.h | 1 +
index.c | 3 +++
read-cache.c | 14 ++++++++++++++
--- Makefile.000 2006-05-07 22:32:04.000000000 +0300
+++ Makefile 2006-05-07 22:30:38.000000000 +0300
@@ -46,6 +46,9 @@
#
# Define NO_MMAP if you want to avoid mmap.
#
+# Define MUMNAP_BEFORE_RENAME if munmap() on target file is required
+# before rename().
+#
# Define WITH_OWN_SUBPROCESS_PY if you want to use with python 2.3.
#
# Define NO_IPV6 if you lack IPv6 support and getaddrinfo().
@@ -270,6 +273,8 @@
# NO_MMAP = YesPlease
NO_IPV6 = YesPlease
X = .exe
+ MUMNAP_BEFORE_RENAME = YesPlease
+ NO_SOCKADDR_STORAGE = YesPlease
endif
ifeq ($(uname_S),FreeBSD)
NEEDS_LIBICONV = YesPlease
--- cache.h.000 2006-05-02 11:35:50.000000000 +0300
+++ cache.h 2006-05-02 11:33:34.000000000 +0300
@@ -140,6 +140,7 @@
/* Initialize and use the cache information */
extern int read_cache(void);
+extern void unmap_cache(void);
extern int write_cache(int newfd, struct cache_entry **cache, int entries);
extern int cache_name_pos(const char *name, int namelen);
#define ADD_CACHE_OK_TO_ADD 1 /* Ok to add */
--- read-cache.c.000 2006-05-07 22:33:42.000000000 +0300
+++ read-cache.c 2006-05-02 11:32:56.000000000 +0300
@@ -513,6 +513,9 @@
return 0;
}
+static void *mapaddr = MAP_FAILED;
+static unsigned long mapsize;
+
int read_cache(void)
{
int fd, i;
@@ -541,6 +544,8 @@
errno = EINVAL;
if (size >= sizeof(struct cache_header) + 20)
map = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0);
+ mapaddr = map;
+ mapsize = size;
}
close(fd);
if (map == MAP_FAILED)
@@ -565,10 +570,19 @@
unmap:
munmap(map, size);
+ mapaddr = MAP_FAILED;
errno = EINVAL;
die("index file corrupt");
}
+void unmap_cache(void)
+{
+ if ( mapaddr != MAP_FAILED ) {
+ munmap(mapaddr, mapsize);
+ mapaddr = MAP_FAILED;
+ }
+}
+
#define WRITE_BUFFER_SIZE 8192
static unsigned char write_buffer[WRITE_BUFFER_SIZE];
static unsigned long write_buffer_len;
--- index.c.000 2006-05-07 22:36:04.000000000 +0300
+++ index.c 2006-05-07 22:36:40.000000000 +0300
@@ -43,6 +43,9 @@
strcpy(indexfile, cf->lockfile);
i = strlen(indexfile) - 5; /* .lock */
indexfile[i] = 0;
+#ifdef MUMNAP_BEFORE_RENAME
+ unmap_cache();
+#endif
i = rename(cf->lockfile, indexfile);
cf->lockfile[0] = 0;
return i;
[-- Attachment #2: patch-munmap-before-rename --]
[-- Type: text/plain, Size: 2237 bytes --]
--- Makefile.000 2006-05-07 22:32:04.000000000 +0300
+++ Makefile 2006-05-07 22:30:38.000000000 +0300
@@ -46,6 +46,9 @@
#
# Define NO_MMAP if you want to avoid mmap.
#
+# Define MUMNAP_BEFORE_RENAME if munmap() on target file is required
+# before rename().
+#
# Define WITH_OWN_SUBPROCESS_PY if you want to use with python 2.3.
#
# Define NO_IPV6 if you lack IPv6 support and getaddrinfo().
@@ -270,6 +273,8 @@
# NO_MMAP = YesPlease
NO_IPV6 = YesPlease
X = .exe
+ MUMNAP_BEFORE_RENAME = YesPlease
+ NO_SOCKADDR_STORAGE = YesPlease
endif
ifeq ($(uname_S),FreeBSD)
NEEDS_LIBICONV = YesPlease
--- cache.h.000 2006-05-02 11:35:50.000000000 +0300
+++ cache.h 2006-05-02 11:33:34.000000000 +0300
@@ -140,6 +140,7 @@
/* Initialize and use the cache information */
extern int read_cache(void);
+extern void unmap_cache(void);
extern int write_cache(int newfd, struct cache_entry **cache, int entries);
extern int cache_name_pos(const char *name, int namelen);
#define ADD_CACHE_OK_TO_ADD 1 /* Ok to add */
--- read-cache.c.000 2006-05-07 22:33:42.000000000 +0300
+++ read-cache.c 2006-05-02 11:32:56.000000000 +0300
@@ -513,6 +513,9 @@
return 0;
}
+static void *mapaddr = MAP_FAILED;
+static unsigned long mapsize;
+
int read_cache(void)
{
int fd, i;
@@ -541,6 +544,8 @@
errno = EINVAL;
if (size >= sizeof(struct cache_header) + 20)
map = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0);
+ mapaddr = map;
+ mapsize = size;
}
close(fd);
if (map == MAP_FAILED)
@@ -565,10 +570,19 @@
unmap:
munmap(map, size);
+ mapaddr = MAP_FAILED;
errno = EINVAL;
die("index file corrupt");
}
+void unmap_cache(void)
+{
+ if ( mapaddr != MAP_FAILED ) {
+ munmap(mapaddr, mapsize);
+ mapaddr = MAP_FAILED;
+ }
+}
+
#define WRITE_BUFFER_SIZE 8192
static unsigned char write_buffer[WRITE_BUFFER_SIZE];
static unsigned long write_buffer_len;
--- index.c.000 2006-05-07 22:36:04.000000000 +0300
+++ index.c 2006-05-07 22:36:40.000000000 +0300
@@ -43,6 +43,9 @@
strcpy(indexfile, cf->lockfile);
i = strlen(indexfile) - 5; /* .lock */
indexfile[i] = 0;
+#ifdef MUMNAP_BEFORE_RENAME
+ unmap_cache();
+#endif
i = rename(cf->lockfile, indexfile);
cf->lockfile[0] = 0;
return i;
^ permalink raw reply
* Re: symlinks
From: Yakov Lerner @ 2006-05-07 19:28 UTC (permalink / raw)
To: Linus Torvalds; +Cc: git
In-Reply-To: <Pine.LNX.4.64.0605071104230.3718@g5.osdl.org>
On 5/7/06, Linus Torvalds <torvalds@osdl.org> wrote:
>
>
> On Sun, 7 May 2006, Yakov Lerner wrote:
> >
> > I have a project that makes heavy use of symlinks in the source tree.
> > I added it to git, then cloned the repository, and all symlinks were
> > converted to plain files. What am I missing to preserve symlinks ?
>
> You're not missing anything, it sounds like a bug. What did you use to
> clone, and what version? It definitely doesn't happen for me:
>
> mkdir symlink
> cd symlink/
> git-init-db
> ln -s unknown new-link
> ls -l
> git add new-link
> git commit
>
> cd
> git clone symlink symlink2
> cd symlink2/
> ls -l
>
> shows that the symlink was preserved.
Yes, I see now it's not git problem. I suspect
I just incorrectly copied the files into git-init-db directory,
something like 'cp -r' instead of 'cp -a' or tar/cpio. Sorry I'm
new to git.
Thanks
Yakov
^ permalink raw reply
* Re: [PATCH] Transitively read alternatives
From: Jakub Narebski @ 2006-05-07 18:28 UTC (permalink / raw)
To: git
In-Reply-To: <20060507181920.GC23738@admingilde.org>
Martin Waitz wrote:
> When adding an alternate object store then add entries from its
> info/alternates files, too.
> Relative entries are only allowed in the current repository.
> Loops and duplicate alternates through multiple repositories are ignored.
> Just to be sure that nothing breaks it is not allow to build deep
> nesting levels using info/alternates.
> + if (depth > 5) {
> + error("%s: ignoring alternate object stores, nesting too deep.",
> + relative_base);
> + return;
> + }
Please, no magic numbers. Use preprocesor "constants" for that.
--
Jakub Narebski
Warsaw, Poland
^ permalink raw reply
* [PATCH] clone: don't clone the info/alternates file
From: Martin Waitz @ 2006-05-07 18:19 UTC (permalink / raw)
To: git
Now that the cloned alternates file is parsed, too we don't need to
copy it into our new repository, we just reference it.
Signed-off-by: Martin Waitz <tali@admingilde.org>
---
git-clone.sh | 6 +-----
1 files changed, 1 insertions(+), 5 deletions(-)
4dc26b7a15c0778459f2ccf85aad1c03d1b3a3cc
diff --git a/git-clone.sh b/git-clone.sh
index b785247..227245c 100755
--- a/git-clone.sh
+++ b/git-clone.sh
@@ -261,11 +261,7 @@ yes,yes)
;;
yes)
mkdir -p "$GIT_DIR/objects/info"
- {
- test -f "$repo/objects/info/alternates" &&
- cat "$repo/objects/info/alternates";
- echo "$repo/objects"
- } >>"$GIT_DIR/objects/info/alternates"
+ echo "$repo/objects" >> "$GIT_DIR/objects/info/alternates"
;;
esac
git-ls-remote "$repo" >"$GIT_DIR/CLONE_HEAD"
--
1.3.1.g6ef7
^ permalink raw reply related
* [PATCH] test case for transitive info/alternates
From: Martin Waitz @ 2006-05-07 18:19 UTC (permalink / raw)
To: git
Signed-off-by: Martin Waitz <tali@admingilde.org>
---
t/t5710-info-alternate.sh | 105 +++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 105 insertions(+), 0 deletions(-)
create mode 100755 t/t5710-info-alternate.sh
47d59f8b0c26226a40344673ecd9e6255a576b98
diff --git a/t/t5710-info-alternate.sh b/t/t5710-info-alternate.sh
new file mode 100755
index 0000000..097d037
--- /dev/null
+++ b/t/t5710-info-alternate.sh
@@ -0,0 +1,105 @@
+#!/bin/sh
+#
+# Copyright (C) 2006 Martin Waitz <tali@admingilde.org>
+#
+
+test_description='test transitive info/alternate entries'
+. ./test-lib.sh
+
+# test that a file is not reachable in the current repository
+# but that it is after creating a info/alternate entry
+reachable_via() {
+ alternate="$1"
+ file="$2"
+ if git cat-file -e "HEAD:$file"; then return 1; fi
+ echo "$alternate" >> .git/objects/info/alternate
+ git cat-file -e "HEAD:$file"
+}
+
+test_valid_repo() {
+ git fsck-objects --full > fsck.log &&
+ test `wc -l < fsck.log` = 0
+}
+
+base_dir=`pwd`
+
+test_expect_success 'preparing first repository' \
+'test_create_repo A && cd A &&
+echo "Hello World" > file1 &&
+git add file1 &&
+git commit -m "Initial commit" file1 &&
+git repack -a -d &&
+git prune'
+
+cd "$base_dir"
+
+test_expect_success 'preparing second repository' \
+'git clone -l -s A B && cd B &&
+echo "foo bar" > file2 &&
+git add file2 &&
+git commit -m "next commit" file2 &&
+git repack -a -d -l &&
+git prune'
+
+cd "$base_dir"
+
+test_expect_success 'preparing third repository' \
+'git clone -l -s B C && cd C &&
+echo "Goodbye, cruel world" > file3 &&
+git add file3 &&
+git commit -m "one more" file3 &&
+git repack -a -d -l &&
+git prune'
+
+cd "$base_dir"
+
+test_expect_failure 'creating too deep nesting' \
+'git clone -l -s C D &&
+git clone -l -s D E &&
+git clone -l -s E F &&
+git clone -l -s F G &&
+test_valid_repo'
+
+cd "$base_dir"
+
+test_expect_success 'validity of third repository' \
+'cd C &&
+test_valid_repo'
+
+cd "$base_dir"
+
+test_expect_success 'validity of fourth repository' \
+'cd D &&
+test_valid_repo'
+
+cd "$base_dir"
+
+test_expect_success 'breaking of loops' \
+"echo '$base_dir/B/.git/objects' >> '$base_dir'/A/.git/objects/info/alternates&&
+cd C &&
+test_valid_repo"
+
+cd "$base_dir"
+
+test_expect_failure 'that info/alternates is neccessary' \
+'cd C &&
+rm .git/objects/info/alternates &&
+test_valid_repo'
+
+cd "$base_dir"
+
+test_expect_success 'that relative alternate is possible for current dir' \
+'cd C &&
+echo "../../../B/.git/objects" > .git/objects/info/alternates &&
+test_valid_repo'
+
+cd "$base_dir"
+
+test_expect_failure 'that relative alternate is only possible for current dir' \
+'cd D &&
+test_valid_repo'
+
+cd "$base_dir"
+
+test_done
+
--
1.3.1.g6ef7
^ permalink raw reply related
* [PATCH] Transitively read alternatives
From: Martin Waitz @ 2006-05-07 18:19 UTC (permalink / raw)
To: git
When adding an alternate object store then add entries from its
info/alternates files, too.
Relative entries are only allowed in the current repository.
Loops and duplicate alternates through multiple repositories are ignored.
Just to be sure that nothing breaks it is not allow to build deep
nesting levels using info/alternates.
Signed-off-by: Martin Waitz <tali@admingilde.org>
---
sha1_file.c | 178 +++++++++++++++++++++++++++++++++++------------------------
1 files changed, 106 insertions(+), 72 deletions(-)
34981f5467a86bb09120cc3c9637b98048fada04
diff --git a/sha1_file.c b/sha1_file.c
index 5464828..b62d0e3 100644
--- a/sha1_file.c
+++ b/sha1_file.c
@@ -217,6 +217,8 @@ char *sha1_pack_index_name(const unsigne
struct alternate_object_database *alt_odb_list;
static struct alternate_object_database **alt_odb_tail;
+static void read_info_alternates(const char * alternates, int depth);
+
/*
* Prepare alternate object database registry.
*
@@ -232,14 +234,85 @@ static struct alternate_object_database
* SHA1, an extra slash for the first level indirection, and the
* terminating NUL.
*/
-static void link_alt_odb_entries(const char *alt, const char *ep, int sep,
- const char *relative_base)
+static int link_alt_odb_entry(const char * entry, int len, const char * relative_base, int depth)
{
- const char *cp, *last;
- struct alternate_object_database *ent;
+ struct stat st;
const char *objdir = get_object_directory();
+ struct alternate_object_database *ent;
+ struct alternate_object_database *alt;
+ /* 43 = 40-byte + 2 '/' + terminating NUL */
+ int pfxlen = len;
+ int entlen = pfxlen + 43;
int base_len = -1;
+ if (*entry != '/' && relative_base) {
+ /* Relative alt-odb */
+ if (base_len < 0)
+ base_len = strlen(relative_base) + 1;
+ entlen += base_len;
+ pfxlen += base_len;
+ }
+ ent = xmalloc(sizeof(*ent) + entlen);
+
+ if (*entry != '/' && relative_base) {
+ memcpy(ent->base, relative_base, base_len - 1);
+ ent->base[base_len - 1] = '/';
+ memcpy(ent->base + base_len, entry, len);
+ }
+ else
+ memcpy(ent->base, entry, pfxlen);
+
+ ent->name = ent->base + pfxlen + 1;
+ ent->base[pfxlen + 3] = '/';
+ ent->base[pfxlen] = ent->base[entlen-1] = 0;
+
+ /* Detect cases where alternate disappeared */
+ if (stat(ent->base, &st) || !S_ISDIR(st.st_mode)) {
+ error("object directory %s does not exist; "
+ "check .git/objects/info/alternates.",
+ ent->base);
+ free(ent);
+ return -1;
+ }
+
+ /* Prevent the common mistake of listing the same
+ * thing twice, or object directory itself.
+ */
+ for (alt = alt_odb_list; alt; alt = alt->next) {
+ if (!memcmp(ent->base, alt->base, pfxlen)) {
+ free(ent);
+ return -1;
+ }
+ }
+ if (!memcmp(ent->base, objdir, pfxlen)) {
+ free(ent);
+ return -1;
+ }
+
+ /* add the alternate entry */
+ *alt_odb_tail = ent;
+ alt_odb_tail = &(ent->next);
+ ent->next = NULL;
+
+ /* recursively add alternates */
+ read_info_alternates(ent->base, depth + 1);
+
+ ent->base[pfxlen] = '/';
+
+ return 0;
+}
+
+static void link_alt_odb_entries(const char *alt, const char *ep, int sep,
+ const char *relative_base, int depth)
+{
+ const char *cp, *last;
+
+ if (depth > 5) {
+ error("%s: ignoring alternate object stores, nesting too deep.",
+ relative_base);
+ return;
+ }
+
last = alt;
while (last < ep) {
cp = last;
@@ -249,60 +322,15 @@ static void link_alt_odb_entries(const c
last = cp + 1;
continue;
}
- for ( ; cp < ep && *cp != sep; cp++)
- ;
+ while (cp < ep && *cp != sep)
+ cp++;
if (last != cp) {
- struct stat st;
- struct alternate_object_database *alt;
- /* 43 = 40-byte + 2 '/' + terminating NUL */
- int pfxlen = cp - last;
- int entlen = pfxlen + 43;
-
- if (*last != '/' && relative_base) {
- /* Relative alt-odb */
- if (base_len < 0)
- base_len = strlen(relative_base) + 1;
- entlen += base_len;
- pfxlen += base_len;
- }
- ent = xmalloc(sizeof(*ent) + entlen);
-
- if (*last != '/' && relative_base) {
- memcpy(ent->base, relative_base, base_len - 1);
- ent->base[base_len - 1] = '/';
- memcpy(ent->base + base_len,
- last, cp - last);
- }
- else
- memcpy(ent->base, last, pfxlen);
-
- ent->name = ent->base + pfxlen + 1;
- ent->base[pfxlen + 3] = '/';
- ent->base[pfxlen] = ent->base[entlen-1] = 0;
-
- /* Detect cases where alternate disappeared */
- if (stat(ent->base, &st) || !S_ISDIR(st.st_mode)) {
- error("object directory %s does not exist; "
- "check .git/objects/info/alternates.",
- ent->base);
- goto bad;
- }
- ent->base[pfxlen] = '/';
-
- /* Prevent the common mistake of listing the same
- * thing twice, or object directory itself.
- */
- for (alt = alt_odb_list; alt; alt = alt->next)
- if (!memcmp(ent->base, alt->base, pfxlen))
- goto bad;
- if (!memcmp(ent->base, objdir, pfxlen)) {
- bad:
- free(ent);
- }
- else {
- *alt_odb_tail = ent;
- alt_odb_tail = &(ent->next);
- ent->next = NULL;
+ if ((*last != '/') && depth) {
+ error("%s: ignoring relative alternate object store %s",
+ relative_base, last);
+ } else {
+ link_alt_odb_entry(last, cp - last,
+ relative_base, depth);
}
}
while (cp < ep && *cp == sep)
@@ -311,23 +339,14 @@ static void link_alt_odb_entries(const c
}
}
-void prepare_alt_odb(void)
+static void read_info_alternates(const char * relative_base, int depth)
{
- char path[PATH_MAX];
char *map;
- int fd;
struct stat st;
- char *alt;
-
- alt = getenv(ALTERNATE_DB_ENVIRONMENT);
- if (!alt) alt = "";
-
- if (alt_odb_tail)
- return;
- alt_odb_tail = &alt_odb_list;
- link_alt_odb_entries(alt, alt + strlen(alt), ':', NULL);
+ char path[PATH_MAX];
+ int fd;
- sprintf(path, "%s/info/alternates", get_object_directory());
+ sprintf(path, "%s/info/alternates", relative_base);
fd = open(path, O_RDONLY);
if (fd < 0)
return;
@@ -340,11 +359,26 @@ void prepare_alt_odb(void)
if (map == MAP_FAILED)
return;
- link_alt_odb_entries(map, map + st.st_size, '\n',
- get_object_directory());
+ link_alt_odb_entries(map, map + st.st_size, '\n', relative_base, depth);
+
munmap(map, st.st_size);
}
+void prepare_alt_odb(void)
+{
+ char *alt;
+
+ alt = getenv(ALTERNATE_DB_ENVIRONMENT);
+ if (!alt) alt = "";
+
+ if (alt_odb_tail)
+ return;
+ alt_odb_tail = &alt_odb_list;
+ link_alt_odb_entries(alt, alt + strlen(alt), ':', NULL, 0);
+
+ read_info_alternates(get_object_directory(), 0);
+}
+
static char *find_sha1_file(const unsigned char *sha1, struct stat *st)
{
char *name = sha1_file_name(sha1);
--
1.3.1.g6ef7
^ permalink raw reply related
* [PATCH] clone: keep --reference even with -l -s
From: Martin Waitz @ 2006-05-07 18:19 UTC (permalink / raw)
To: git
Both -l -s and --reference update objects/info/alternates and used
to write over each other.
Signed-off-by: Martin Waitz <tali@admingilde.org>
---
git-clone.sh | 2 +
t/t5700-clone-reference.sh | 78 ++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 79 insertions(+), 1 deletions(-)
create mode 100755 t/t5700-clone-reference.sh
3410837e34357d43a38a170691ca45f8f3a82221
diff --git a/git-clone.sh b/git-clone.sh
index 0805168..b785247 100755
--- a/git-clone.sh
+++ b/git-clone.sh
@@ -265,7 +265,7 @@ yes,yes)
test -f "$repo/objects/info/alternates" &&
cat "$repo/objects/info/alternates";
echo "$repo/objects"
- } >"$GIT_DIR/objects/info/alternates"
+ } >>"$GIT_DIR/objects/info/alternates"
;;
esac
git-ls-remote "$repo" >"$GIT_DIR/CLONE_HEAD"
diff --git a/t/t5700-clone-reference.sh b/t/t5700-clone-reference.sh
new file mode 100755
index 0000000..916ee15
--- /dev/null
+++ b/t/t5700-clone-reference.sh
@@ -0,0 +1,78 @@
+#!/bin/sh
+#
+# Copyright (C) 2006 Martin Waitz <tali@admingilde.org>
+#
+
+test_description='test clone --reference'
+. ./test-lib.sh
+
+base_dir=`pwd`
+
+test_expect_success 'preparing first repository' \
+'test_create_repo A && cd A &&
+echo first > file1 &&
+git add file1 &&
+git commit -m initial'
+
+cd "$base_dir"
+
+test_expect_success 'preparing second repository' \
+'git clone A B && cd B &&
+echo second > file2 &&
+git add file2 &&
+git commit -m addition &&
+git repack -a -d &&
+git prune'
+
+cd "$base_dir"
+
+test_expect_success 'cloning with reference' \
+'git clone -l -s --reference B A C'
+
+cd "$base_dir"
+
+test_expect_success 'existance of info/alternates' \
+'test `wc -l <C/.git/objects/info/alternates` = 2'
+
+cd "$base_dir"
+
+test_expect_success 'pulling from reference' \
+'cd C &&
+git pull ../B'
+
+cd "$base_dir"
+
+test_expect_success 'that reference gets used' \
+'cd C &&
+echo "0 objects, 0 kilobytes" > expected &&
+git count-objects > current &&
+diff expected current'
+
+cd "$base_dir"
+
+test_expect_success 'updating origin' \
+'cd A &&
+echo third > file3 &&
+git add file3 &&
+git commit -m update &&
+git repack -a -d &&
+git prune'
+
+cd "$base_dir"
+
+test_expect_success 'pulling changes from origin' \
+'cd C &&
+git pull origin'
+
+cd "$base_dir"
+
+# the 2 local objects are commit and tree from the merge
+test_expect_success 'that alternate to origin gets used' \
+'cd C &&
+echo "2 objects" > expected &&
+git count-objects | cut -d, -f1 > current &&
+diff expected current'
+
+cd "$base_dir"
+
+test_done
--
1.3.1.g6ef7
^ permalink raw reply related
* [PATCH] repack: honor -d even when no new pack was created
From: Martin Waitz @ 2006-05-07 18:18 UTC (permalink / raw)
To: git
If all objects are reachable via an alternate object store then we
still have to remove all obsolete local packs.
Signed-off-by: Martin Waitz <tali@admingilde.org>
---
git-repack.sh | 14 +++++++-------
1 files changed, 7 insertions(+), 7 deletions(-)
c37df94d2b1633ce329bbe079805073b40a48548
diff --git a/git-repack.sh b/git-repack.sh
index e0c9f32..4fb3f26 100755
--- a/git-repack.sh
+++ b/git-repack.sh
@@ -48,15 +48,15 @@ name=$(git-rev-list --objects --all $rev
exit 1
if [ -z "$name" ]; then
echo Nothing new to pack.
- exit 0
-fi
-echo "Pack pack-$name created."
+else
+ echo "Pack pack-$name created."
-mkdir -p "$PACKDIR" || exit
+ mkdir -p "$PACKDIR" || exit
-mv .tmp-pack-$name.pack "$PACKDIR/pack-$name.pack" &&
-mv .tmp-pack-$name.idx "$PACKDIR/pack-$name.idx" ||
-exit
+ mv .tmp-pack-$name.pack "$PACKDIR/pack-$name.pack" &&
+ mv .tmp-pack-$name.idx "$PACKDIR/pack-$name.idx" ||
+ exit
+fi
if test "$remove_redundant" = t
then
--
1.3.1.g6ef7
^ permalink raw reply related
* Re: symlinks
From: Linus Torvalds @ 2006-05-07 18:07 UTC (permalink / raw)
To: Yakov Lerner; +Cc: git
In-Reply-To: <f36b08ee0605071047h32ccef4bk76ac360ada1331a@mail.gmail.com>
On Sun, 7 May 2006, Yakov Lerner wrote:
>
> I have a project that makes heavy use of symlinks in the source tree.
> I added it to git, then cloned the repository, and all symlinks were
> converted to plain files. What am I missing to preserve symlinks ?
You're not missing anything, it sounds like a bug. What did you use to
clone, and what version? It definitely doesn't happen for me:
mkdir symlink
cd symlink/
git-init-db
ln -s unknown new-link
ls -l
git add new-link
git commit
cd
git clone symlink symlink2
cd symlink2/
ls -l
shows that the symlink was preserved.
But maybe there's a bug in some older version, or in some other clone
protocol...
Linus
^ permalink raw reply
* symlinks
From: Yakov Lerner @ 2006-05-07 17:47 UTC (permalink / raw)
To: git
Hello,
I have a project that makes heavy use of symlinks in the source tree.
I added it to git, then cloned the repository, and all symlinks were
converted to plain files. What am I missing to preserve symlinks ?
Yakov
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox