* Re: [PATCH] Do _not_ call unlink on a directory
From: Linus Torvalds @ 2007-07-17 19:07 UTC (permalink / raw)
To: Junio C Hamano; +Cc: Thomas Glanzmann, git
In-Reply-To: <7vtzs3a0xg.fsf@assigned-by-dhcp.cox.net>
On Tue, 17 Jul 2007, Junio C Hamano wrote:
>
> This is wrong. If the filesystem has a symlink and we would
> want a directory there, we should unlink(). So at least the
> stat there needs to be lstat().
Good catch. Ack.
Linus
^ permalink raw reply
* Re: Installation failure caused by CDPATH environment variable
From: Wincent Colaiuta @ 2007-07-17 19:07 UTC (permalink / raw)
To: Junio C Hamano; +Cc: Uwe Kleine-König, git
In-Reply-To: <7vhco2ancg.fsf@assigned-by-dhcp.cox.net>
El 17/7/2007, a las 20:37, Junio C Hamano escribió:
> Uwe Kleine-König <ukleinek@informatik.uni-freiburg.de> writes:
>
>> Junio C Hamano wrote:
>>> We could write it as "$(TAR) Ccf blt - ." if we can rely on the
>>> 'C' option, but I suspect it is a GNU extension. Does anybody
>>> have POSIX.1 handy?
>> I don't have POSIX.1 handy, but on Solaris 10, you need to say:
>>
>> tar cf - -C blt .
>>
>> (That is, Solaris' tar has the 'C' option, which is quite a good
>> indication, that it's included in POSIX :-)
>
> Oh, I cannot resist ;-)
>
> Solaris has unlink(2) capable of removing a directory, but I do
> not think it is included in POSIX.
I'd say the answer is "no", "C" isn't in the POSIX tar specification.
The latest, Version 3, says "the Shell and Utilities volume of IEEE
Std 1003.1-2001 no longer contains the tar utility" (<http://
www.opengroup.org/onlinepubs/009695399/basedefs/tar.h.html>).
And Version 2, which does contain tar, does not list "C" as an option
(<http://www.opengroup.org/onlinepubs/7990989775/xcu/tar.html>).
In fact, the example they give for moving directory hierarchies is
exactly this:
(cd fromdir; tar cf - . ) | (cd todir; tar xf -)
Cheers,
Wincent
^ permalink raw reply
* [PATCH] gitweb: snapshot cleanups & support for offering multiple formats
From: Matt McCutchen @ 2007-07-17 19:11 UTC (permalink / raw)
To: Junio C Hamano; +Cc: Jakub Narebski, git, Petr Baudis, Luben Tuikov
In-Reply-To: <3bbc18d20707171103q262eaa8amb319ca9f835dbf67@mail.gmail.com>
- Centralize knowledge about snapshot formats (mime types, extensions,
commands) in %known_snapshot_formats and improve how some of that
information is specified. In particular, zip files are no longer a
special case.
- Add support for offering multiple snapshot formats to the user so
that he/she can download a snapshot in the format he/she prefers.
The site-wide or project configuration now gives a list of formats
to offer, and if more than one format is offered, the "_snapshot_"
link becomes something like "snapshot (_tar.bz2_ _zip_)".
- If only one format is offered, a tooltip on the "_snapshot_" link
tells the user what it is.
- Fix out-of-date "tarball" -> "archive" in comment.
Alert for gitweb site administrators: This patch changes the format of
$feature{'snapshot'}{'default'} in gitweb_config.perl from a list of
three pieces of information about a single format to a list of one or
more formats you wish to offer from the set ('tgz', 'tbz2', 'zip').
Update your gitweb_config.perl appropriately. The preferred names for
gitweb.snapshot in repository configuration have also changed from
'gzip' and 'bzip2' to 'tgz' and 'tbz2', but the old names are still
recognized for compatibility.
Signed-off-by: Matt McCutchen <hashproduct@gmail.com>
---
Changes since the previous revision of the patch:
- Added display names.
- Changed compressor command line to list form.
- Added compatibility format aliases for repository configuration.
- Tweaked filtering of unknown formats to apply only to repository
configuration.
- Reformatted format_snapshot_links and added/modified comments to make it much
easier to understand.
- When a single snapshot format is offered, added a tooltip showing the format
to the "snapshot" link. This helps Junio's hypothetical end user without
using additional screen real estate.
I thought of another incompatibility: previously bookmarked snapshot
URLs will no longer work because they lack the new "sf" parameter. I
don't care about this; do any of you?
Is there anything else I need to do to the patch? If not, how soon is
it likely to be committed? I'm guessing I missed the boat on git 1.5.3.
Matt
gitweb/gitweb.perl | 134 +++++++++++++++++++++++++++++++++-------------------
1 files changed, 86 insertions(+), 48 deletions(-)
diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl
index c8ba3a2..f17c983 100755
--- a/gitweb/gitweb.perl
+++ b/gitweb/gitweb.perl
@@ -104,6 +104,22 @@ our $mimetypes_file = undef;
# could be even 'utf-8' for the old behavior)
our $fallback_encoding = 'latin1';
+# information about snapshot formats that gitweb is capable of serving
+# name => [display name, mime type, filename suffix, --format for git-archive,
+# [compressor command and arguments] | undef]
+our %known_snapshot_formats = (
+ 'tgz' => ['tar.gz' , 'application/x-gzip' , '.tar.gz' , 'tar', ['gzip' ]],
+ 'tbz2' => ['tar.bz2', 'application/x-bzip2', '.tar.bz2', 'tar', ['bzip2']],
+ 'zip' => ['zip', 'application/x-zip' , '.zip' , 'zip', undef ],
+);
+
+# Aliases so we understand old gitweb.snapshot values in repository
+# configuration.
+our %known_snapshot_format_aliases = (
+ 'gzip' => 'tgz' ,
+ 'bzip2' => 'tbz2',
+);
+
# You define site-wide feature defaults here; override them with
# $GITWEB_CONFIG as necessary.
our %feature = (
@@ -134,20 +150,22 @@ our %feature = (
'override' => 0,
'default' => [0]},
- # Enable the 'snapshot' link, providing a compressed tarball of any
+ # Enable the 'snapshot' link, providing a compressed archive of any
# tree. This can potentially generate high traffic if you have large
# project.
+ # Value is a list of formats defined in %known_snapshot_formats that
+ # you wish to offer.
# To disable system wide have in $GITWEB_CONFIG
- # $feature{'snapshot'}{'default'} = [undef];
+ # $feature{'snapshot'}{'default'} = [];
# To have project specific config enable override in $GITWEB_CONFIG
# $feature{'snapshot'}{'override'} = 1;
- # and in project config gitweb.snapshot = none|gzip|bzip2|zip;
+ # and in project config, a comma-separated list of formats or "none"
+ # to disable. Example: gitweb.snapshot = tbz2,zip;
'snapshot' => {
'sub' => \&feature_snapshot,
'override' => 0,
- # => [content-encoding, suffix, program]
- 'default' => ['x-gzip', 'gz', 'gzip']},
+ 'default' => ['tgz']},
# Enable text search, which will list the commits which match author,
# committer or commit text to a given string. Enabled by default.
@@ -246,28 +264,17 @@ sub feature_blame {
}
sub feature_snapshot {
- my ($ctype, $suffix, $command) = @_;
+ my (@fmts) = @_;
my ($val) = git_get_project_config('snapshot');
- if ($val eq 'gzip') {
- return ('x-gzip', 'gz', 'gzip');
- } elsif ($val eq 'bzip2') {
- return ('x-bzip2', 'bz2', 'bzip2');
- } elsif ($val eq 'zip') {
- return ('x-zip', 'zip', '');
- } elsif ($val eq 'none') {
- return ();
+ if ($val) {
+ @fmts = ($val eq 'none' ? () : split /,/, $val);
+ @fmts = map $known_snapshot_format_aliases{$_} || $_, @fmts;
+ @fmts = grep exists $known_snapshot_formats{$_}, @fmts;
}
- return ($ctype, $suffix, $command);
-}
-
-sub gitweb_have_snapshot {
- my ($ctype, $suffix, $command) = gitweb_check_feature('snapshot');
- my $have_snapshot = (defined $ctype && defined $suffix);
-
- return $have_snapshot;
+ return @fmts;
}
sub feature_grep {
@@ -563,6 +570,7 @@ sub href(%) {
order => "o",
searchtext => "s",
searchtype => "st",
+ snapshot_format => "sf",
);
my %mapping = @mapping;
@@ -1257,6 +1265,39 @@ sub format_diff_line {
return "<div class=\"diff$diff_class\">" . esc_html($line, -nbsp=>1) . "</div>\n";
}
+# Generates undef or something like "_snapshot_" or "snapshot (_tbz2_ _zip_)",
+# linked. Pass the hash of the tree/commit to snapshot.
+sub format_snapshot_links {
+ my ($hash) = @_;
+ my @snapshot_fmts = gitweb_check_feature('snapshot');
+ my $num_fmts = @snapshot_fmts;
+ if ($num_fmts > 1) {
+ # A parenthesized list of links bearing format names.
+ return "snapshot (" . join(' ', map
+ $cgi->a({
+ -href => href(
+ action=>"snapshot",
+ hash=>$hash,
+ snapshot_format=>$_
+ )
+ }, $known_snapshot_formats{$_}[0]) # the display name
+ , @snapshot_fmts) . ")";
+ } elsif ($num_fmts == 1) {
+ # A single "snapshot" link whose tooltip bears the format name.
+ my ($fmt) = @snapshot_fmts;
+ return $cgi->a({
+ -href => href(
+ action=>"snapshot",
+ hash=>$hash,
+ snapshot_format=>$fmt
+ ),
+ -title => "in format: $known_snapshot_formats{$fmt}[0]" # the display name
+ }, "snapshot");
+ } else { # $num_fmts == 0
+ return undef;
+ }
+}
+
## ----------------------------------------------------------------------
## git utility subroutines, invoking git commands
@@ -3321,8 +3362,6 @@ sub git_shortlog_body {
# uses global variable $project
my ($commitlist, $from, $to, $refs, $extra) = @_;
- my $have_snapshot = gitweb_have_snapshot();
-
$from = 0 unless defined $from;
$to = $#{$commitlist} if (!defined $to || $#{$commitlist} < $to);
@@ -3349,8 +3388,9 @@ sub git_shortlog_body {
$cgi->a({-href => href(action=>"commit", hash=>$commit)}, "commit") . " | " .
$cgi->a({-href => href(action=>"commitdiff", hash=>$commit)}, "commitdiff") . " | " .
$cgi->a({-href => href(action=>"tree", hash=>$commit, hash_base=>$commit)}, "tree");
- if ($have_snapshot) {
- print " | " . $cgi->a({-href => href(action=>"snapshot", hash=>$commit)}, "snapshot");
+ my $snapshot_links = format_snapshot_links($commit);
+ if (defined $snapshot_links) {
+ print " | " . $snapshot_links;
}
print "</td>\n" .
"</tr>\n";
@@ -4132,8 +4172,6 @@ sub git_blob {
}
sub git_tree {
- my $have_snapshot = gitweb_have_snapshot();
-
if (!defined $hash_base) {
$hash_base = "HEAD";
}
@@ -4167,11 +4205,10 @@ sub git_tree {
hash_base=>"HEAD", file_name=>$file_name)},
"HEAD"),
}
- if ($have_snapshot) {
+ my $snapshot_links = format_snapshot_links($hash);
+ if (defined $snapshot_links) {
# FIXME: Should be available when we have no hash base as well.
- push @views_nav,
- $cgi->a({-href => href(action=>"snapshot", hash=>$hash)},
- "snapshot");
+ push @views_nav, $snapshot_links;
}
git_print_page_nav('tree','', $hash_base, undef, undef, join(' | ', @views_nav));
git_print_header_div('commit', esc_html($co{'title'}) . $ref, $hash_base);
@@ -4235,11 +4272,16 @@ sub git_tree {
}
sub git_snapshot {
- my ($ctype, $suffix, $command) = gitweb_check_feature('snapshot');
- my $have_snapshot = (defined $ctype && defined $suffix);
- if (!$have_snapshot) {
- die_error('403 Permission denied', "Permission denied");
+ my @supported_fmts = gitweb_check_feature('snapshot');
+
+ my $format = $cgi->param('sf');
+ unless ($format =~ m/[a-z0-9]+/
+ && exists($known_snapshot_formats{$format})
+ && grep($_ eq $format, @supported_fmts)) {
+ die_error(undef, "Unsupported snapshot format");
}
+ my ($dispname, $ctype, $suffix, $ga_format, $compressor_argv) =
+ @{$known_snapshot_formats{$format}};
if (!defined $hash) {
$hash = git_get_head_hash($project);
@@ -4252,16 +4294,14 @@ sub git_snapshot {
my $filename = to_utf8($name);
$name =~ s/\047/\047\\\047\047/g;
my $cmd;
- if ($suffix eq 'zip') {
- $filename .= "-$hash.$suffix";
- $cmd = "$git archive --format=zip --prefix=\'$name\'/ $hash";
- } else {
- $filename .= "-$hash.tar.$suffix";
- $cmd = "$git archive --format=tar --prefix=\'$name\'/ $hash | $command";
+ $filename .= "-$hash$suffix";
+ $cmd = "$git archive --format=$ga_format --prefix=\'$name\'/ $hash";
+ if (defined $compressor_argv) {
+ $cmd .= ' | ' . join ' ', @$compressor_argv;
}
print $cgi->header(
- -type => "application/$ctype",
+ -type => "$ctype",
-content_disposition => 'inline; filename="' . "$filename" . '"',
-status => '200 OK');
@@ -4390,8 +4430,6 @@ sub git_commit {
my $refs = git_get_references();
my $ref = format_ref_marker($refs, $co{'id'});
- my $have_snapshot = gitweb_have_snapshot();
-
git_header_html(undef, $expires);
git_print_page_nav('commit', '',
$hash, $co{'tree'}, $hash,
@@ -4430,9 +4468,9 @@ sub git_commit {
"<td class=\"link\">" .
$cgi->a({-href => href(action=>"tree", hash=>$co{'tree'}, hash_base=>$hash)},
"tree");
- if ($have_snapshot) {
- print " | " .
- $cgi->a({-href => href(action=>"snapshot", hash=>$hash)}, "snapshot");
+ my $snapshot_links = format_snapshot_links($hash);
+ if (defined $snapshot_links) {
+ print " | " . $snapshot_links;
}
print "</td>" .
"</tr>\n";
--
1.5.3.rc2.6.gf09b
^ permalink raw reply related
* git-log: --topo-order speed-ups the thing !?
From: Marco Costalba @ 2007-07-17 19:13 UTC (permalink / raw)
To: Git Mailing List
Testing with git log performance on Linux tree I found this
interesting and unexpected result:
$ time git log --parents --boundary --pretty=raw -z --log-size
--topo-order HEAD > /dev/null
6.85user 0.20system 0:07.05elapsed 100%CPU (0avgtext+0avgdata 0maxresident)k
0inputs+0outputs (0major+21142minor)pagefaults 0swaps
$ time git log --parents --boundary --pretty=raw -z --log-size HEAD > /dev/null
7.01user 0.09system 0:07.10elapsed 100%CPU (0avgtext+0avgdata 0maxresident)k
0inputs+0outputs (0major+11128minor)pagefaults 0swaps
Although page faults are more or less the half, execution time is
faster _with_ --topo-order option.
Someone could explain why?
Thanks
Marco
^ permalink raw reply
* Re: Do a better job at guessing unknown character sets
From: Johannes Schindelin @ 2007-07-17 19:56 UTC (permalink / raw)
To: Linus Torvalds; +Cc: Junio C Hamano, Git Mailing List
In-Reply-To: <alpine.LFD.0.999.0707171027100.19166@woody.linux-foundation.org>
Hi,
On Tue, 17 Jul 2007, Linus Torvalds wrote:
> I think this makes sense from a "the world is moving to utf-8"
> standpoint, even if obviously some people might consider it a bit ugly
> to do per-line "guessing".
>
> Comments?
IMHO this is a good change. Encodings are such a hassle, and probably
only because the inventors of ASCII just were narrow-minded enough not to
care. With this patch, the hassle factor diminishes AFAICT.
Ciao,
Dscho
P.S.: I think that in case of undesired behaviour, even if it is detected
late in the game, filter-branch/rewrite-commits will help.
^ permalink raw reply
* Re: Do a better job at guessing unknown character sets
From: david @ 2007-07-17 20:01 UTC (permalink / raw)
To: Johannes Schindelin; +Cc: Linus Torvalds, Junio C Hamano, Git Mailing List
In-Reply-To: <Pine.LNX.4.64.0707172053030.14781@racer.site>
On Tue, 17 Jul 2007, Johannes Schindelin wrote:
> On Tue, 17 Jul 2007, Linus Torvalds wrote:
>
>> I think this makes sense from a "the world is moving to utf-8"
>> standpoint, even if obviously some people might consider it a bit ugly
>> to do per-line "guessing".
>>
>> Comments?
>
> Encodings are such a hassle, and probably
> only because the inventors of ASCII just were narrow-minded enough not to
> care.
to be perfectly fair, at the time ASCII was invented it was done to
eliminate the use of the different, incompatible character sets that were
in use at the time. And it did the job well (I think the only surviver
from those sets is EBCDIC, and only due to the legacy installed base)
current character encodings are doing things that weren't dreamed of by
anyone at the time.
David Lang
^ permalink raw reply
* gitweb: get_file_owner and XML special characters
From: Eddie Kohler @ 2007-07-17 20:06 UTC (permalink / raw)
To: git
[-- Attachment #1: Type: text/plain, Size: 351 bytes --]
Hi,
I think current gitweb generates invalid XHTML when get_file_owner returns a
string containing <>&. (Version 1.5.2.1 certainly does, and in a quick browse
of current source I didn't notice relevant changes.)
Here is a dirty patch to fix this problem. Apologies if it is no longer a
problem or if the patch is gross.
Thanks,
Eddie (newbie)
[-- Attachment #2: 0001-Escape-HTML-special-characters-in-file-owner.patch --]
[-- Type: text/x-patch, Size: 687 bytes --]
>From 1c6ba7b6b28808cea0f2f9ab46733ddefdac329a Mon Sep 17 00:00:00 2001
From: Eddie Kohler <kohler@cs.ucla.edu>
Date: Tue, 17 Jul 2007 13:06:08 -0700
Subject: [PATCH] Escape HTML special characters in file owner
---
gitweb/gitweb.perl | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl
index c8ba3a2..540d9a6 100755
--- a/gitweb/gitweb.perl
+++ b/gitweb/gitweb.perl
@@ -2050,7 +2050,7 @@ sub get_file_owner {
}
my $owner = $gcos;
$owner =~ s/[,;].*$//;
- return to_utf8($owner);
+ return $cgi->escapeHTML(to_utf8($owner));
}
## ......................................................................
--
1.5.2.2
^ permalink raw reply related
* Re: Installation failure caused by CDPATH environment variable
From: Uwe Kleine-König @ 2007-07-17 20:19 UTC (permalink / raw)
To: Junio C Hamano; +Cc: Wincent Colaiuta, git
In-Reply-To: <7vhco2ancg.fsf@assigned-by-dhcp.cox.net>
Hello Junio,
Junio C Hamano wrote:
> Uwe Kleine-König <ukleinek@informatik.uni-freiburg.de> writes:
> > (That is, Solaris' tar has the 'C' option, which is quite a good
> > indication, that it's included in POSIX :-)
>
> Oh, I cannot resist ;-)
>
> Solaris has unlink(2) capable of removing a directory, but I do
> not think it is included in POSIX.
I don't have access to the POSIX documents, but it would surprise me if
they forbid unlink(2) being able to unlink directories. :-)
You need some effort to support tar -C and to catch directories in
unlink. So Sun put the effort in tar, because it may be needed to be
conformant to POSIX or some other standard.
Best regards
Uwe
--
Uwe Kleine-König
<script>alert("This is a virus for Outlook")</script>
^ permalink raw reply
* Re: [PATCH] Do _not_ call unlink on a directory
From: Thomas Glanzmann @ 2007-07-17 20:27 UTC (permalink / raw)
To: Junio C Hamano; +Cc: git
In-Reply-To: <7vlkdeang0.fsf@assigned-by-dhcp.cox.net>
Hello Junio,
> Ahhhh, by "testing", I meant "runnnig the testsuite shipped with
> the source". Both of your patches were failing in somewhere in
> t2000 series of tests.
That was the last time, I am going to submit a patch _without_ running
the whole testsuite before. I hate it myself when other people don't do
the obvious tests and break something that worked before.
> I am thinking that this fix should go to 'maint' and merged to
> 'master', as it is a grave problem in at least one setup.
Thanks. For packages that I distribute, I fixed it of course by myself.
And to be precise I use git on Solaris a lot by myself but I don't work
as root so the bug never showed up before and as you can see by the
pastes that I provided to track down the bug I have
if [ $UID -eq 0 ]; then
export PS1="(${PROMPT_RED}\h${PROMPT_END}) [${PROMPT_BLUE}\w${PROMPT_END}] ";
alias bk='echo DO *NOT* RUN BK AS ROOT'
alias git='echo DO *NOT* RUN GIT AS ROOT'
alias links='echo DO *NOT* RUN LINKS AS ROOT'
alias elinks='echo DO *NOT* RUN ELINKS AS ROOT'
...
in my distributed environment. But my coworker who I "show" git to work
a lot as root. A very bad habbit that is hard to get rid of. Btw. I
prepare to setup a automatic build script which I am going to let run
automatic on a daily basis so that I catch Solaris compile problems
early and report them to you.
Thomas
^ permalink raw reply
* Re: [PATCH] git-svn: Minimalistic patch which allows svn usernames with space(s).
From: Eric Wong @ 2007-07-17 19:55 UTC (permalink / raw)
To: Richard MUSIL; +Cc: git
In-Reply-To: <469CF641.4020707@st.com>
Richard MUSIL <richard.musil@st.com> wrote:
> Changed filter for username in svn-authors file, so even 'user name' is accepted.
> ---
> git-svn.perl | 2 +-
> 1 files changed, 1 insertions(+), 1 deletions(-)
>
> diff --git a/git-svn.perl b/git-svn.perl
> index 01c3904..975075e 100755
> --- a/git-svn.perl
> +++ b/git-svn.perl
> @@ -740,7 +740,7 @@ sub load_authors {
> my $log = $cmd eq 'log';
> while (<$authors>) {
> chomp;
> - next unless /^(\S+?|\(no author\))\s*=\s*(.+?)\s*<(.+)>\s*$/;
> + next unless /^(\.+?|\(no author\))\s*=\s*(.+?)\s*<(.+)>\s*$/;
Surely you mean the following:
+ next unless /^(.+?|\(no author\))\s*=\s*(.+?)\s*<(.+)>\s*$/;
(No "\" before the ".") "\." matches a dot/period (.), while "."
matches anything.
--
Eric Wong
^ permalink raw reply
* Re: git-config: replaces ~/.gitconfig symlink with real file
From: Fredrik Tolf @ 2007-07-17 20:35 UTC (permalink / raw)
To: git
In-Reply-To: <Pine.LNX.4.64.0707170834040.14781@racer.site>
Johannes Schindelin <Johannes.Schindelin@gmx.de> writes:
> Hi,
>
> On Mon, 16 Jul 2007, Bradford Smith wrote:
>
>> So, I guess I need to add a GIT_CONFIG_HOME environment variable. If I
>> get that done, I'll send a patch to the list including doc updates.
>
> Alternatively, you could actually not ignore my hint at readlink(2) and
> have a proper fix, instead of playing games with environment variables.
Wouldn't it be nicer to avoid a lot of the complexity in checking
symlinks, environment variables and what not, and just overwrite the
file in place (with open(..., O_TRUNC | O_CREAT))? Does it happen
terribly often that git-config crashes in the middle and leaves the
file broken?
Fredrik Tolf
^ permalink raw reply
* Re: git-config: replaces ~/.gitconfig symlink with real file
From: Johannes Schindelin @ 2007-07-17 20:48 UTC (permalink / raw)
To: Fredrik Tolf; +Cc: git
In-Reply-To: <m3wswyojj2.fsf@pc7.dolda2000.com>
Hi,
On Tue, 17 Jul 2007, Fredrik Tolf wrote:
> Johannes Schindelin <Johannes.Schindelin@gmx.de> writes:
>
> > On Mon, 16 Jul 2007, Bradford Smith wrote:
> >
> >> So, I guess I need to add a GIT_CONFIG_HOME environment variable. If I
> >> get that done, I'll send a patch to the list including doc updates.
> >
> > Alternatively, you could actually not ignore my hint at readlink(2) and
> > have a proper fix, instead of playing games with environment variables.
>
> Wouldn't it be nicer to avoid a lot of the complexity in checking
> symlinks, environment variables and what not, and just overwrite the
> file in place (with open(..., O_TRUNC | O_CREAT))? Does it happen
> terribly often that git-config crashes in the middle and leaves the file
> broken?
No, it does not. But when it does, I am not only annoyed. I am PISSED!
The way we do it is the only safe way to do it, and I gladly spend some
extra cycles for that. Too often, a small hard disk glitch (or just an
empty laptop battery!) took some important data into the void. Too often,
I _cursed_ at the machine, even if it was the programmers' fault.
Ciao,
Dscho
^ permalink raw reply
* Re: 'git gc' & number of unpacked objects ?
From: Sam Vilain @ 2007-07-17 20:57 UTC (permalink / raw)
To: Yakov Lerner; +Cc: Git Mailing List
In-Reply-To: <f36b08ee0707170914g7ece7124qf5d8d6a1307cc07e@mail.gmail.com>
Yakov Lerner wrote:
> By the analogy with the maxtime and maxmount in the ext3 when it
> reminds you to fsck, when number of mounts since last fsck, or time since
> last fsck is above some limits. I think this makes practical sense. I
> think
> the similar thing makes sense wrt to 'git gc'.
>
> Is it possible that git repo had a parameter N, and when the counter of
> unpacked object hit this number, then git operations start to print
> semi-annoying warnings
> "Time to optimize your repo using 'git gc' command ... "
> ?
I also wrote a commit hook that counts loose objects and just runs
repack with differing parameters. Check for threads with terms
"generational repack" in them.
To make it a really fast check, Linus suggested estimating the number of
loose objects with a sample, eg if the threshold is 256 loose objects
and you find 3 or more objects in directories 01, 02, and 03 then it's
time to repack.
I've been using the script I posted on my own repositories for a while
and was never really annoyed by the 2-3s aside it took every few dozen
commits to repack. But then I'm probably biased and usually playing on
relatively zippy machines.
Sam.
^ permalink raw reply
* [PATCH] git-gui: Handle git versions of the form n.n.n.GIT
From: Julian Phillips @ 2007-07-17 21:14 UTC (permalink / raw)
To: Shawn O. Pearce; +Cc: git
In-Reply-To: <Pine.LNX.4.64.0707171244080.13359@reaper.quantumfyre.co.uk>
The git-gui version check doesn't handle versions of the form
n.n.n.GIT which you can get by installing from an tarball produced by
git-archive.
Without this change you get an error of the form:
'Error in startup script: expected version number but got "1.5.3.GIT"'
Signed-off-by: Julian Phillips <julian@quantumfyre.co.uk>
---
> I have a machine on which git was installed from a tarball created by
> running git-archive on master (so a 1.5.3ish version).
>
> When I try running git-gui I get an error message:
>
> 'Error in startup script: expected version number but got "1.5.3.GIT"'
>
> followed by what I assume is a code snippet where it failed (I wouldn't
> know tcl if it hit me with a large brick).
>
> Is this expected? driver error? or maybe a bug?
Well, whichever it is, this seems to fix it for me ... with the proviso that I
still no nothing about tcl. I am also not sure if it is correct to do the
patch against the git repo?
git-gui/git-gui.sh | 1 +
1 files changed, 1 insertions(+), 0 deletions(-)
diff --git a/git-gui/git-gui.sh b/git-gui/git-gui.sh
index 2077261..f8b1f10 100755
--- a/git-gui/git-gui.sh
+++ b/git-gui/git-gui.sh
@@ -546,6 +546,7 @@ if {![regsub {^git version } $_git_version {} _git_version]} {
}
regsub {\.[0-9]+\.g[0-9a-f]+$} $_git_version {} _git_version
regsub {\.rc[0-9]+$} $_git_version {} _git_version
+regsub {\.GIT$} $_git_version {} _git_version
proc git-version {args} {
global _git_version
--
1.5.2.2
^ permalink raw reply related
* Re: [PATCH] git-gui: Handle git versions of the form n.n.n.GIT
From: Brian Downing @ 2007-07-17 21:40 UTC (permalink / raw)
To: Julian Phillips; +Cc: Shawn O. Pearce, git
In-Reply-To: <20070717212103.11950.10363.julian@quantumfyre.co.uk>
On Tue, Jul 17, 2007 at 10:14:06PM +0100, Julian Phillips wrote:
> The git-gui version check doesn't handle versions of the form
> n.n.n.GIT which you can get by installing from an tarball produced by
> git-archive.
>
> Without this change you get an error of the form:
> 'Error in startup script: expected version number but got "1.5.3.GIT"'
Can we handle versions with '-dirty' at the end as well, or is this
ill-advised? For some reason when I build my hacked-up personal debian
packages it usually winds up:
:; git --version
git version 1.5.3.GIT-dirty
and I haven't bothered to find out why.
-bcd
^ permalink raw reply
* Re: [PATCH] git-gui: Handle git versions of the form n.n.n.GIT
From: Brian Downing @ 2007-07-17 21:45 UTC (permalink / raw)
To: Julian Phillips; +Cc: Shawn O. Pearce, git
In-Reply-To: <20070717214011.GU19073@lavos.net>
On Tue, Jul 17, 2007 at 04:40:12PM -0500, Brian Downing wrote:
> Can we handle versions with '-dirty' at the end as well, or is this
> ill-advised? For some reason when I build my hacked-up personal debian
> packages it usually winds up:
>
> :; git --version
> git version 1.5.3.GIT-dirty
>
> and I haven't bothered to find out why.
D'oh, now I know why. I'm trying git to keep my home directory config
stuff versioned, so GIT-VERSION-GEN, failing to find a .git directory
in my tar export, digs down and finds my home directory one instead.
I take it this means that keeping your home directory under git
/directly/ as I have chosen to do is a bad idea...
-bcd
^ permalink raw reply
* Re: [PATCH] git-gui: Handle git versions of the form n.n.n.GIT
From: Jason Sewall @ 2007-07-17 21:49 UTC (permalink / raw)
To: Brian Downing; +Cc: Julian Phillips, Shawn O. Pearce, git
In-Reply-To: <20070717214510.GV19073@lavos.net>
On 7/17/07, Brian Downing <bdowning@lavos.net> wrote:
> I take it this means that keeping your home directory under git
> /directly/ as I have chosen to do is a bad idea...
Interesting, because this is something I've wanted to do - I use
several machines (work, work laptop, home, home laptop) and I'm always
tweaking my various dotfiles... I could really use a way to keep them
all synchronized.
Just out of curiosity, what do you people do?
Jason
^ permalink raw reply
* Re: [PATCH] git-gui: Handle git versions of the form n.n.n.GIT
From: Linus Torvalds @ 2007-07-17 22:34 UTC (permalink / raw)
To: Brian Downing; +Cc: Julian Phillips, Shawn O. Pearce, git
In-Reply-To: <20070717214510.GV19073@lavos.net>
On Tue, 17 Jul 2007, Brian Downing wrote:
>
> D'oh, now I know why. I'm trying git to keep my home directory config
> stuff versioned, so GIT-VERSION-GEN, failing to find a .git directory
> in my tar export, digs down and finds my home directory one instead.
Ok, that's definitely a git misfeature.
I think we could probably add a check something like:
- once we have found a .git directory by walking up the tree, the
directory we actually came _from_ should then be tracked by that git
directory.
but I wonder how to do that properly (we would probably need to load the
index, which we generally don't want to do).
Linus
^ permalink raw reply
* (no subject)
From: Mark Levedahl @ 2007-07-17 22:39 UTC (permalink / raw)
To: paulus, Git Mailing List
From 567906ddb2fbbcf07325acc2808346ad6a472df1 Mon Sep 17 00:00:00 2001
From: Mark Levedahl <mdl123@verizon.net>
Date: Tue, 17 Jul 2007 18:35:46 -0400
Subject: [PATCH] gitk - Ignore ctrl-z as EOF on windows
To: mlevedahl@verizon.net
-=-=-=-=-=-=-=-=-=# Don't remove this line #=-=-=-=-=-=-=-=-=-
Cygwin's Tcl is configured to honor any occurence of ctrl-z as an
end-of-file marker, while some commits in the git repository and possibly
elsewhere include that character in the commit comment. This causes gitk
ignore commit history following such a comment and incorrect graphs. This
change affects only Windows as Tcl on other platforms already has
eofchar == {}. This fixes problems noted by me and by Ray Lehtiniemi, and
the fix was suggested by Shawn Pierce.
Signed-off-by: Mark Levedahl <mdl123@verizon.net>
---
gitk | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/gitk b/gitk
index 39e452a..238607e 100755
--- a/gitk
+++ b/gitk
@@ -101,7 +101,7 @@ proc start_rev_list {view} {
set commfd($view) $fd
set leftover($view) {}
set lookingforhead $showlocalchanges
- fconfigure $fd -blocking 0 -translation lf
+ fconfigure $fd -blocking 0 -translation lf -eofchar {}
if {$tclencoding != {}} {
fconfigure $fd -encoding $tclencoding
}
--
1.5.3.rc2.5.g66bbd
^ permalink raw reply related
* [PATCH] gitk - Ignore ctrl-z as EOF on windows
From: Mark Levedahl @ 2007-07-17 22:42 UTC (permalink / raw)
To: paulus, Git Mailing List; +Cc: Mark Levedahl
Cygwin's Tcl is configured to honor any occurence of ctrl-z as an
end-of-file marker, while some commits in the git repository and possibly
elsewhere include that character in the commit comment. This causes gitk
ignore commit history following such a comment and incorrect graphs. This
change affects only Windows as Tcl on other platforms already has
eofchar == {}. This fixes problems noted by me and by Ray Lehtiniemi, and
the fix was suggested by Shawn Pierce.
Signed-off-by: Mark Levedahl <mdl123@verizon.net>
---
gitk | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/gitk b/gitk
index 39e452a..238607e 100755
--- a/gitk
+++ b/gitk
@@ -101,7 +101,7 @@ proc start_rev_list {view} {
set commfd($view) $fd
set leftover($view) {}
set lookingforhead $showlocalchanges
- fconfigure $fd -blocking 0 -translation lf
+ fconfigure $fd -blocking 0 -translation lf -eofchar {}
if {$tclencoding != {}} {
fconfigure $fd -encoding $tclencoding
}
--
1.5.3.rc2.5.g66bbd
^ permalink raw reply related
* [PATCH 1/3] Move bundle specific stuff into bundle.[ch]
From: Johannes Schindelin @ 2007-07-17 22:49 UTC (permalink / raw)
To: git, Daniel Barkalow
The transport specific stuff was moved into libgit.a, and the
bundle specific stuff will not be left behind.
This is a big code move, with one exception: the function
unbundle() no longer outputs the list of refs. You have to call
list_bundle_refs() yourself for that.
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
---
FWIW this patch series is based on the bf_series branch of
git://iabervon.org/~barkalow/git.git, revision a204e4b4.
Makefile | 2 +-
builtin-bundle.c | 330 +-----------------------------------------------------
bundle.c | 310 ++++++++++++++++++++++++++++++++++++++++++++++++++
bundle.h | 25 ++++
4 files changed, 342 insertions(+), 325 deletions(-)
create mode 100644 bundle.c
create mode 100644 bundle.h
diff --git a/Makefile b/Makefile
index 335be8f..a389ee7 100644
--- a/Makefile
+++ b/Makefile
@@ -318,7 +318,7 @@ LIB_OBJS = \
alloc.o merge-file.o path-list.o help.o unpack-trees.o $(DIFF_OBJS) \
color.o wt-status.o archive-zip.o archive-tar.o shallow.o utf8.o \
convert.o attr.o decorate.o progress.o mailmap.o symlinks.o remote.o \
- transport.o
+ transport.o bundle.o
BUILTIN_OBJS = \
builtin-add.o \
diff --git a/builtin-bundle.c b/builtin-bundle.c
index 306ad29..22d03a3 100644
--- a/builtin-bundle.c
+++ b/builtin-bundle.c
@@ -1,10 +1,5 @@
#include "cache.h"
-#include "object.h"
-#include "commit.h"
-#include "diff.h"
-#include "revision.h"
-#include "list-objects.h"
-#include "run-command.h"
+#include "bundle.h"
/*
* Basic handler for bundle files to connect repositories via sneakernet.
@@ -15,320 +10,6 @@
static const char *bundle_usage="git-bundle (create <bundle> <git-rev-list args> | verify <bundle> | list-heads <bundle> [refname]... | unbundle <bundle> [refname]... )";
-static const char bundle_signature[] = "# v2 git bundle\n";
-
-struct ref_list {
- unsigned int nr, alloc;
- struct ref_list_entry {
- unsigned char sha1[20];
- char *name;
- } *list;
-};
-
-static void add_to_ref_list(const unsigned char *sha1, const char *name,
- struct ref_list *list)
-{
- if (list->nr + 1 >= list->alloc) {
- list->alloc = alloc_nr(list->nr + 1);
- list->list = xrealloc(list->list,
- list->alloc * sizeof(list->list[0]));
- }
- memcpy(list->list[list->nr].sha1, sha1, 20);
- list->list[list->nr].name = xstrdup(name);
- list->nr++;
-}
-
-struct bundle_header {
- struct ref_list prerequisites;
- struct ref_list references;
-};
-
-/* this function returns the length of the string */
-static int read_string(int fd, char *buffer, int size)
-{
- int i;
- for (i = 0; i < size - 1; i++) {
- ssize_t count = xread(fd, buffer + i, 1);
- if (count < 0)
- return error("Read error: %s", strerror(errno));
- if (count == 0) {
- i--;
- break;
- }
- if (buffer[i] == '\n')
- break;
- }
- buffer[i + 1] = '\0';
- return i + 1;
-}
-
-/* returns an fd */
-static int read_header(const char *path, struct bundle_header *header) {
- char buffer[1024];
- int fd = open(path, O_RDONLY);
-
- if (fd < 0)
- return error("could not open '%s'", path);
- if (read_string(fd, buffer, sizeof(buffer)) < 0 ||
- strcmp(buffer, bundle_signature)) {
- close(fd);
- return error("'%s' does not look like a v2 bundle file", path);
- }
- while (read_string(fd, buffer, sizeof(buffer)) > 0
- && buffer[0] != '\n') {
- int is_prereq = buffer[0] == '-';
- int offset = is_prereq ? 1 : 0;
- int len = strlen(buffer);
- unsigned char sha1[20];
- struct ref_list *list = is_prereq ? &header->prerequisites
- : &header->references;
- char delim;
-
- if (buffer[len - 1] == '\n')
- buffer[len - 1] = '\0';
- if (get_sha1_hex(buffer + offset, sha1)) {
- warning("unrecognized header: %s", buffer);
- continue;
- }
- delim = buffer[40 + offset];
- if (!isspace(delim) && (delim != '\0' || !is_prereq))
- die ("invalid header: %s", buffer);
- add_to_ref_list(sha1, isspace(delim) ?
- buffer + 41 + offset : "", list);
- }
- return fd;
-}
-
-static int list_refs(struct ref_list *r, int argc, const char **argv)
-{
- int i;
-
- for (i = 0; i < r->nr; i++) {
- if (argc > 1) {
- int j;
- for (j = 1; j < argc; j++)
- if (!strcmp(r->list[i].name, argv[j]))
- break;
- if (j == argc)
- continue;
- }
- printf("%s %s\n", sha1_to_hex(r->list[i].sha1),
- r->list[i].name);
- }
- return 0;
-}
-
-#define PREREQ_MARK (1u<<16)
-
-static int verify_bundle(struct bundle_header *header, int verbose)
-{
- /*
- * Do fast check, then if any prereqs are missing then go line by line
- * to be verbose about the errors
- */
- struct ref_list *p = &header->prerequisites;
- struct rev_info revs;
- const char *argv[] = {NULL, "--all"};
- struct object_array refs;
- struct commit *commit;
- int i, ret = 0, req_nr;
- const char *message = "Repository lacks these prerequisite commits:";
-
- init_revisions(&revs, NULL);
- for (i = 0; i < p->nr; i++) {
- struct ref_list_entry *e = p->list + i;
- struct object *o = parse_object(e->sha1);
- if (o) {
- o->flags |= PREREQ_MARK;
- add_pending_object(&revs, o, e->name);
- continue;
- }
- if (++ret == 1)
- error(message);
- error("%s %s", sha1_to_hex(e->sha1), e->name);
- }
- if (revs.pending.nr != p->nr)
- return ret;
- req_nr = revs.pending.nr;
- setup_revisions(2, argv, &revs, NULL);
-
- memset(&refs, 0, sizeof(struct object_array));
- for (i = 0; i < revs.pending.nr; i++) {
- struct object_array_entry *e = revs.pending.objects + i;
- add_object_array(e->item, e->name, &refs);
- }
-
- prepare_revision_walk(&revs);
-
- i = req_nr;
- while (i && (commit = get_revision(&revs)))
- if (commit->object.flags & PREREQ_MARK)
- i--;
-
- for (i = 0; i < req_nr; i++)
- if (!(refs.objects[i].item->flags & SHOWN)) {
- if (++ret == 1)
- error(message);
- error("%s %s", sha1_to_hex(refs.objects[i].item->sha1),
- refs.objects[i].name);
- }
-
- for (i = 0; i < refs.nr; i++)
- clear_commit_marks((struct commit *)refs.objects[i].item, -1);
-
- if (verbose) {
- struct ref_list *r;
-
- r = &header->references;
- printf("The bundle contains %d ref%s\n",
- r->nr, (1 < r->nr) ? "s" : "");
- list_refs(r, 0, NULL);
- r = &header->prerequisites;
- printf("The bundle requires these %d ref%s\n",
- r->nr, (1 < r->nr) ? "s" : "");
- list_refs(r, 0, NULL);
- }
- return ret;
-}
-
-static int list_heads(struct bundle_header *header, int argc, const char **argv)
-{
- return list_refs(&header->references, argc, argv);
-}
-
-static int create_bundle(struct bundle_header *header, const char *path,
- int argc, const char **argv)
-{
- int bundle_fd = -1;
- const char **argv_boundary = xmalloc((argc + 4) * sizeof(const char *));
- const char **argv_pack = xmalloc(5 * sizeof(const char *));
- int i, ref_count = 0;
- char buffer[1024];
- struct rev_info revs;
- struct child_process rls;
-
- bundle_fd = (!strcmp(path, "-") ? 1 :
- open(path, O_CREAT | O_EXCL | O_WRONLY, 0666));
- if (bundle_fd < 0)
- return error("Could not create '%s': %s", path, strerror(errno));
-
- /* write signature */
- write_or_die(bundle_fd, bundle_signature, strlen(bundle_signature));
-
- /* init revs to list objects for pack-objects later */
- save_commit_buffer = 0;
- init_revisions(&revs, NULL);
-
- /* write prerequisites */
- memcpy(argv_boundary + 3, argv + 1, argc * sizeof(const char *));
- argv_boundary[0] = "rev-list";
- argv_boundary[1] = "--boundary";
- argv_boundary[2] = "--pretty=oneline";
- argv_boundary[argc + 2] = NULL;
- memset(&rls, 0, sizeof(rls));
- rls.argv = argv_boundary;
- rls.out = -1;
- rls.git_cmd = 1;
- if (start_command(&rls))
- return -1;
- while ((i = read_string(rls.out, buffer, sizeof(buffer))) > 0) {
- unsigned char sha1[20];
- if (buffer[0] == '-') {
- write_or_die(bundle_fd, buffer, i);
- if (!get_sha1_hex(buffer + 1, sha1)) {
- struct object *object = parse_object(sha1);
- object->flags |= UNINTERESTING;
- add_pending_object(&revs, object, buffer);
- }
- } else if (!get_sha1_hex(buffer, sha1)) {
- struct object *object = parse_object(sha1);
- object->flags |= SHOWN;
- }
- }
- if (finish_command(&rls))
- return error("rev-list died");
-
- /* write references */
- argc = setup_revisions(argc, argv, &revs, NULL);
- if (argc > 1)
- return error("unrecognized argument: %s'", argv[1]);
-
- for (i = 0; i < revs.pending.nr; i++) {
- struct object_array_entry *e = revs.pending.objects + i;
- unsigned char sha1[20];
- char *ref;
-
- if (e->item->flags & UNINTERESTING)
- continue;
- if (dwim_ref(e->name, strlen(e->name), sha1, &ref) != 1)
- continue;
- /*
- * Make sure the refs we wrote out is correct; --max-count and
- * other limiting options could have prevented all the tips
- * from getting output.
- */
- if (!(e->item->flags & SHOWN)) {
- warning("ref '%s' is excluded by the rev-list options",
- e->name);
- continue;
- }
- ref_count++;
- write_or_die(bundle_fd, sha1_to_hex(e->item->sha1), 40);
- write_or_die(bundle_fd, " ", 1);
- write_or_die(bundle_fd, ref, strlen(ref));
- write_or_die(bundle_fd, "\n", 1);
- free(ref);
- }
- if (!ref_count)
- die ("Refusing to create empty bundle.");
-
- /* end header */
- write_or_die(bundle_fd, "\n", 1);
-
- /* write pack */
- argv_pack[0] = "pack-objects";
- argv_pack[1] = "--all-progress";
- argv_pack[2] = "--stdout";
- argv_pack[3] = "--thin";
- argv_pack[4] = NULL;
- memset(&rls, 0, sizeof(rls));
- rls.argv = argv_pack;
- rls.in = -1;
- rls.out = bundle_fd;
- rls.git_cmd = 1;
- if (start_command(&rls))
- return error("Could not spawn pack-objects");
- for (i = 0; i < revs.pending.nr; i++) {
- struct object *object = revs.pending.objects[i].item;
- if (object->flags & UNINTERESTING)
- write(rls.in, "^", 1);
- write(rls.in, sha1_to_hex(object->sha1), 40);
- write(rls.in, "\n", 1);
- }
- if (finish_command(&rls))
- return error ("pack-objects died");
- return 0;
-}
-
-static int unbundle(struct bundle_header *header, int bundle_fd,
- int argc, const char **argv)
-{
- const char *argv_index_pack[] = {"index-pack",
- "--fix-thin", "--stdin", NULL};
- struct child_process ip;
-
- if (verify_bundle(header, 0))
- return -1;
- memset(&ip, 0, sizeof(ip));
- ip.argv = argv_index_pack;
- ip.in = bundle_fd;
- ip.no_stdout = 1;
- ip.git_cmd = 1;
- if (run_command(&ip))
- return error("index-pack died");
- return list_heads(header, argc, argv);
-}
-
int cmd_bundle(int argc, const char **argv, const char *prefix)
{
struct bundle_header header;
@@ -352,8 +33,8 @@ int cmd_bundle(int argc, const char **argv, const char *prefix)
}
memset(&header, 0, sizeof(header));
- if (strcmp(cmd, "create") &&
- (bundle_fd = read_header(bundle_file, &header)) < 0)
+ if (strcmp(cmd, "create") && (bundle_fd =
+ read_bundle_header(bundle_file, &header)) < 0)
return 1;
if (!strcmp(cmd, "verify")) {
@@ -365,7 +46,7 @@ int cmd_bundle(int argc, const char **argv, const char *prefix)
}
if (!strcmp(cmd, "list-heads")) {
close(bundle_fd);
- return !!list_heads(&header, argc, argv);
+ return !!list_bundle_refs(&header, argc, argv);
}
if (!strcmp(cmd, "create")) {
if (nongit)
@@ -374,7 +55,8 @@ int cmd_bundle(int argc, const char **argv, const char *prefix)
} else if (!strcmp(cmd, "unbundle")) {
if (nongit)
die("Need a repository to unbundle.");
- return !!unbundle(&header, bundle_fd, argc, argv);
+ return !!unbundle(&header, bundle_fd) ||
+ list_bundle_refs(&header, argc, argv);
} else
usage(bundle_usage);
}
diff --git a/bundle.c b/bundle.c
new file mode 100644
index 0000000..659b61d
--- /dev/null
+++ b/bundle.c
@@ -0,0 +1,310 @@
+#include "cache.h"
+#include "bundle.h"
+#include "object.h"
+#include "commit.h"
+#include "diff.h"
+#include "revision.h"
+#include "list-objects.h"
+#include "run-command.h"
+
+static const char bundle_signature[] = "# v2 git bundle\n";
+
+static void add_to_ref_list(const unsigned char *sha1, const char *name,
+ struct ref_list *list)
+{
+ if (list->nr + 1 >= list->alloc) {
+ list->alloc = alloc_nr(list->nr + 1);
+ list->list = xrealloc(list->list,
+ list->alloc * sizeof(list->list[0]));
+ }
+ memcpy(list->list[list->nr].sha1, sha1, 20);
+ list->list[list->nr].name = xstrdup(name);
+ list->nr++;
+}
+
+/* this function returns the length of the string */
+static int read_string(int fd, char *buffer, int size)
+{
+ int i;
+ for (i = 0; i < size - 1; i++) {
+ ssize_t count = xread(fd, buffer + i, 1);
+ if (count < 0)
+ return error("Read error: %s", strerror(errno));
+ if (count == 0) {
+ i--;
+ break;
+ }
+ if (buffer[i] == '\n')
+ break;
+ }
+ buffer[i + 1] = '\0';
+ return i + 1;
+}
+
+/* returns an fd */
+int read_bundle_header(const char *path, struct bundle_header *header) {
+ char buffer[1024];
+ int fd = open(path, O_RDONLY);
+
+ if (fd < 0)
+ return error("could not open '%s'", path);
+ if (read_string(fd, buffer, sizeof(buffer)) < 0 ||
+ strcmp(buffer, bundle_signature)) {
+ close(fd);
+ return error("'%s' does not look like a v2 bundle file", path);
+ }
+ while (read_string(fd, buffer, sizeof(buffer)) > 0
+ && buffer[0] != '\n') {
+ int is_prereq = buffer[0] == '-';
+ int offset = is_prereq ? 1 : 0;
+ int len = strlen(buffer);
+ unsigned char sha1[20];
+ struct ref_list *list = is_prereq ? &header->prerequisites
+ : &header->references;
+ char delim;
+
+ if (buffer[len - 1] == '\n')
+ buffer[len - 1] = '\0';
+ if (get_sha1_hex(buffer + offset, sha1)) {
+ warning("unrecognized header: %s", buffer);
+ continue;
+ }
+ delim = buffer[40 + offset];
+ if (!isspace(delim) && (delim != '\0' || !is_prereq))
+ die ("invalid header: %s", buffer);
+ add_to_ref_list(sha1, isspace(delim) ?
+ buffer + 41 + offset : "", list);
+ }
+ return fd;
+}
+
+int create_bundle(struct bundle_header *header, const char *path,
+ int argc, const char **argv)
+{
+ int bundle_fd = -1;
+ const char **argv_boundary = xmalloc((argc + 4) * sizeof(const char *));
+ const char **argv_pack = xmalloc(5 * sizeof(const char *));
+ int i, ref_count = 0;
+ char buffer[1024];
+ struct rev_info revs;
+ struct child_process rls;
+
+ bundle_fd = (!strcmp(path, "-") ? 1 :
+ open(path, O_CREAT | O_EXCL | O_WRONLY, 0666));
+ if (bundle_fd < 0)
+ return error("Could not create '%s': %s", path, strerror(errno));
+
+ /* write signature */
+ write_or_die(bundle_fd, bundle_signature, strlen(bundle_signature));
+
+ /* init revs to list objects for pack-objects later */
+ save_commit_buffer = 0;
+ init_revisions(&revs, NULL);
+
+ /* write prerequisites */
+ memcpy(argv_boundary + 3, argv + 1, argc * sizeof(const char *));
+ argv_boundary[0] = "rev-list";
+ argv_boundary[1] = "--boundary";
+ argv_boundary[2] = "--pretty=oneline";
+ argv_boundary[argc + 2] = NULL;
+ memset(&rls, 0, sizeof(rls));
+ rls.argv = argv_boundary;
+ rls.out = -1;
+ rls.git_cmd = 1;
+ if (start_command(&rls))
+ return -1;
+ while ((i = read_string(rls.out, buffer, sizeof(buffer))) > 0) {
+ unsigned char sha1[20];
+ if (buffer[0] == '-') {
+ write_or_die(bundle_fd, buffer, i);
+ if (!get_sha1_hex(buffer + 1, sha1)) {
+ struct object *object = parse_object(sha1);
+ object->flags |= UNINTERESTING;
+ add_pending_object(&revs, object, buffer);
+ }
+ } else if (!get_sha1_hex(buffer, sha1)) {
+ struct object *object = parse_object(sha1);
+ object->flags |= SHOWN;
+ }
+ }
+ if (finish_command(&rls))
+ return error("rev-list died");
+
+ /* write references */
+ argc = setup_revisions(argc, argv, &revs, NULL);
+ if (argc > 1)
+ return error("unrecognized argument: %s'", argv[1]);
+
+ for (i = 0; i < revs.pending.nr; i++) {
+ struct object_array_entry *e = revs.pending.objects + i;
+ unsigned char sha1[20];
+ char *ref;
+
+ if (e->item->flags & UNINTERESTING)
+ continue;
+ if (dwim_ref(e->name, strlen(e->name), sha1, &ref) != 1)
+ continue;
+ /*
+ * Make sure the refs we wrote out is correct; --max-count and
+ * other limiting options could have prevented all the tips
+ * from getting output.
+ */
+ if (!(e->item->flags & SHOWN)) {
+ warning("ref '%s' is excluded by the rev-list options",
+ e->name);
+ continue;
+ }
+ ref_count++;
+ write_or_die(bundle_fd, sha1_to_hex(e->item->sha1), 40);
+ write_or_die(bundle_fd, " ", 1);
+ write_or_die(bundle_fd, ref, strlen(ref));
+ write_or_die(bundle_fd, "\n", 1);
+ free(ref);
+ }
+ if (!ref_count)
+ die ("Refusing to create empty bundle.");
+
+ /* end header */
+ write_or_die(bundle_fd, "\n", 1);
+
+ /* write pack */
+ argv_pack[0] = "pack-objects";
+ argv_pack[1] = "--all-progress";
+ argv_pack[2] = "--stdout";
+ argv_pack[3] = "--thin";
+ argv_pack[4] = NULL;
+ memset(&rls, 0, sizeof(rls));
+ rls.argv = argv_pack;
+ rls.in = -1;
+ rls.out = bundle_fd;
+ rls.git_cmd = 1;
+ if (start_command(&rls))
+ return error("Could not spawn pack-objects");
+ for (i = 0; i < revs.pending.nr; i++) {
+ struct object *object = revs.pending.objects[i].item;
+ if (object->flags & UNINTERESTING)
+ write(rls.in, "^", 1);
+ write(rls.in, sha1_to_hex(object->sha1), 40);
+ write(rls.in, "\n", 1);
+ }
+ if (finish_command(&rls))
+ return error ("pack-objects died");
+ return 0;
+}
+
+static int list_refs(struct ref_list *r, int argc, const char **argv)
+{
+ int i;
+
+ for (i = 0; i < r->nr; i++) {
+ if (argc > 1) {
+ int j;
+ for (j = 1; j < argc; j++)
+ if (!strcmp(r->list[i].name, argv[j]))
+ break;
+ if (j == argc)
+ continue;
+ }
+ printf("%s %s\n", sha1_to_hex(r->list[i].sha1),
+ r->list[i].name);
+ }
+ return 0;
+}
+
+int list_bundle_refs(struct bundle_header *header, int argc, const char **argv)
+{
+ return list_refs(&header->references, argc, argv);
+}
+
+#define PREREQ_MARK (1u<<16)
+
+int verify_bundle(struct bundle_header *header, int verbose)
+{
+ /*
+ * Do fast check, then if any prereqs are missing then go line by line
+ * to be verbose about the errors
+ */
+ struct ref_list *p = &header->prerequisites;
+ struct rev_info revs;
+ const char *argv[] = {NULL, "--all"};
+ struct object_array refs;
+ struct commit *commit;
+ int i, ret = 0, req_nr;
+ const char *message = "Repository lacks these prerequisite commits:";
+
+ init_revisions(&revs, NULL);
+ for (i = 0; i < p->nr; i++) {
+ struct ref_list_entry *e = p->list + i;
+ struct object *o = parse_object(e->sha1);
+ if (o) {
+ o->flags |= PREREQ_MARK;
+ add_pending_object(&revs, o, e->name);
+ continue;
+ }
+ if (++ret == 1)
+ error(message);
+ error("%s %s", sha1_to_hex(e->sha1), e->name);
+ }
+ if (revs.pending.nr != p->nr)
+ return ret;
+ req_nr = revs.pending.nr;
+ setup_revisions(2, argv, &revs, NULL);
+
+ memset(&refs, 0, sizeof(struct object_array));
+ for (i = 0; i < revs.pending.nr; i++) {
+ struct object_array_entry *e = revs.pending.objects + i;
+ add_object_array(e->item, e->name, &refs);
+ }
+
+ prepare_revision_walk(&revs);
+
+ i = req_nr;
+ while (i && (commit = get_revision(&revs)))
+ if (commit->object.flags & PREREQ_MARK)
+ i--;
+
+ for (i = 0; i < req_nr; i++)
+ if (!(refs.objects[i].item->flags & SHOWN)) {
+ if (++ret == 1)
+ error(message);
+ error("%s %s", sha1_to_hex(refs.objects[i].item->sha1),
+ refs.objects[i].name);
+ }
+
+ for (i = 0; i < refs.nr; i++)
+ clear_commit_marks((struct commit *)refs.objects[i].item, -1);
+
+ if (verbose) {
+ struct ref_list *r;
+
+ r = &header->references;
+ printf("The bundle contains %d ref%s\n",
+ r->nr, (1 < r->nr) ? "s" : "");
+ list_refs(r, 0, NULL);
+ r = &header->prerequisites;
+ printf("The bundle requires these %d ref%s\n",
+ r->nr, (1 < r->nr) ? "s" : "");
+ list_refs(r, 0, NULL);
+ }
+ return ret;
+}
+
+int unbundle(struct bundle_header *header, int bundle_fd)
+{
+ const char *argv_index_pack[] = {"index-pack",
+ "--fix-thin", "--stdin", NULL};
+ struct child_process ip;
+
+ if (verify_bundle(header, 0))
+ return -1;
+ memset(&ip, 0, sizeof(ip));
+ ip.argv = argv_index_pack;
+ ip.in = bundle_fd;
+ ip.no_stdout = 1;
+ ip.git_cmd = 1;
+ if (run_command(&ip))
+ return error("index-pack died");
+ return 0;
+}
+
+
diff --git a/bundle.h b/bundle.h
new file mode 100644
index 0000000..e2aedd6
--- /dev/null
+++ b/bundle.h
@@ -0,0 +1,25 @@
+#ifndef BUNDLE_H
+#define BUNDLE_H
+
+struct ref_list {
+ unsigned int nr, alloc;
+ struct ref_list_entry {
+ unsigned char sha1[20];
+ char *name;
+ } *list;
+};
+
+struct bundle_header {
+ struct ref_list prerequisites;
+ struct ref_list references;
+};
+
+int read_bundle_header(const char *path, struct bundle_header *header);
+int create_bundle(struct bundle_header *header, const char *path,
+ int argc, const char **argv);
+int verify_bundle(struct bundle_header *header, int verbose);
+int unbundle(struct bundle_header *header, int bundle_fd);
+int list_bundle_refs(struct bundle_header *header,
+ int argc, const char **argv);
+
+#endif
--
1.5.3.rc1.16.g9d6f-dirty
^ permalink raw reply related
* [PATCH 2/3] Add bundle transport
From: Johannes Schindelin @ 2007-07-17 22:49 UTC (permalink / raw)
To: git, Daniel Barkalow
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
---
transport.c | 52 +++++++++++++++++++++++++++++++++++++++++++++++++++-
1 files changed, 51 insertions(+), 1 deletions(-)
diff --git a/transport.c b/transport.c
index f444c5b..1532276 100644
--- a/transport.c
+++ b/transport.c
@@ -5,6 +5,7 @@
#include "pkt-line.h"
#include "fetch-pack.h"
#include "walker.h"
+#include "bundle.h"
/* Generic functions for using commit walkers */
@@ -185,7 +186,55 @@ static const struct transport_ops curl_transport = {
/* disconnect */ disconnect_walker
};
+struct bundle_transport_data {
+ int fd;
+ struct bundle_header header;
+};
+
+static struct ref *get_refs_from_bundle(const struct transport *transport)
+{
+ struct bundle_transport_data *data = transport->data;
+ struct ref *result = NULL;
+ int i;
+
+ if (data->fd > 0)
+ close(data->fd);
+ data->fd = read_bundle_header(transport->url, &data->header);
+ if (data->fd < 0)
+ die ("Could not read bundle '%s'.", transport->url);
+ for (i = 0; i < data->header.references.nr; i++) {
+ struct ref_list_entry *e = data->header.references.list + i;
+ struct ref *ref = alloc_ref(strlen(e->name));
+ hashcpy(ref->old_sha1, e->sha1);
+ strcpy(ref->name, e->name);
+ ref->next = result;
+ result = ref;
+ }
+ return result;
+}
+
+static int fetch_refs_from_bundle(const struct transport *transport,
+ int nr_heads, char **heads)
+{
+ struct bundle_transport_data *data = transport->data;
+ return unbundle(&data->header, data->fd);
+}
+
+static int close_bundle(struct transport *transport)
+{
+ struct bundle_transport_data *data = transport->data;
+ if (data->fd > 0)
+ close(data->fd);
+ return 0;
+}
+
static const struct transport_ops bundle_transport = {
+ /* set_option */ NULL,
+ /* get_refs_list */ get_refs_from_bundle,
+ /* fetch_refs */ fetch_refs_from_bundle,
+ /* fetch_objs */ NULL,
+ /* push */ NULL,
+ /* disconnect */ close_bundle
};
struct git_transport_data {
@@ -359,8 +408,9 @@ struct transport *transport_get(struct remote *remote, const char *url,
else
ret->data = NULL;
} else if (is_local(url) && is_file(url)) {
+ struct bundle_transport_data *data = xcalloc(1, sizeof(*data));
ret = xmalloc(sizeof(*ret));
- ret->data = NULL;
+ ret->data = data;
ret->ops = &bundle_transport;
} else {
struct git_transport_data *data = xcalloc(1, sizeof(*data));
--
1.5.3.rc1.16.g9d6f-dirty
^ permalink raw reply related
* [PATCH 3/3] builtin-fetch: fail when fetching refs fails
From: Johannes Schindelin @ 2007-07-17 22:50 UTC (permalink / raw)
To: git, Daniel Barkalow
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
---
builtin-fetch.c | 5 ++++-
1 files changed, 4 insertions(+), 1 deletions(-)
diff --git a/builtin-fetch.c b/builtin-fetch.c
index 2f24c22..f1045ac 100644
--- a/builtin-fetch.c
+++ b/builtin-fetch.c
@@ -381,7 +381,10 @@ static int do_fetch(struct transport *transport,
}
}
- fetch_refs(transport, ref_map);
+ if (fetch_refs(transport, ref_map)) {
+ free_refs(ref_map);
+ return 1;
+ }
fetch_map = ref_map;
--
1.5.3.rc1.16.g9d6f-dirty
^ permalink raw reply related
* Character set for the HTML documentation
From: H. Peter Anvin @ 2007-07-17 23:31 UTC (permalink / raw)
To: Git Mailing List, Junio C Hamano
I just got the following email:
> The Git documentation at
> <http://www.kernel.org/pub/software/scm/git/docs/user-manual.html> is
> encoded in ISO 8859-1, but it is being served with a content-type header
> of "text/plain; charset=UTF-8".
>
> The content-type header overrides the value declared in the <meta> tag
> of the HTML document, so this causes browsers to render the
> documentation incorrectly.
>
> Apologies if this is a well known issue and you get a lot of mail like
> this BTW, just don't LART me too hard. ;)
The fact that browsers behave this way is of course a bug, but it's a
common one. Can we switch the documentation over to UTF-8, this is 2007
after all...?
-hpa
^ permalink raw reply
* Empty directories...
From: David Kastrup @ 2007-07-18 0:13 UTC (permalink / raw)
To: git
GIT(7) -- 03/05/2007
NAME
git - the stupid content tracker
Well, I use git for tracking contents. That means, for example,
installation trees for some application. Let's take a typical TeXlive
tree as an example. Those trees contain, among other things,
directories where new fonts/formats/whatever get placed as things run.
Quite a few of them start out empty, but their permissions have to
correspond to their purpose (for example, some are world-writable).
I see little chance to get this achieved without doing something like
find -type d -empty -execdir touch {}/.git-this-is-empty +
before every checkin and
find -name .git-this-is-empty -exec rm -- {} +
after every checkout. Which is pretty stupid.
As some anecdotal stuff, I did something like
mkdir test
cd test
git-init
touch README
git-add README # another peeve: why is no empty reference point possible?
git-commit -a -m "Initial branch"
git checkout -b newbranch master
unzip ../somearchive -d subdir
git add subdir
git commit -a -m "Add subdir"
git checkout -b newbranch2 master
and expect to have a clean slate. No such luck: without warning, all
empty directories in the zip file are still remaining within subdir,
which as a consequence has not been cleaned up.
So even if one is of the opinion that empty directories are not worth
putting into the repository: if I check in an entire subdirectory
hierarchy and then switch to a branch where this subdirectory is not
existent, I expect the subdirectory to be _gone_, and not have some
littering of empty directories lying around.
And that git-diff can see nothing wrong with that does not really
improve things.
So if git is supposed to be a content tracker, I can't see a way
around it actually being able to track content, and empty directories
_are_ content. It can't let them flying around with arbitrary
permissions on them when I switch branches or tags. And the
workaround using "touch" mentioned above is really awful to do
manually all the time.
Could git technically track a file with a zero-length filename in
empty directories if one tells it explicitly to include it, like with
git-add \! -x "" subdir
or has somebody a better idea or interface or rationale? I understand
that there are use cases where one does not bother about empty
directories, but for a _content_ tracker, not tracking directories
because they are empty seems quite serious.
Ok, kill me. This must likely be the most common FAQ/rant/whatever
concerning git.
--
David Kastrup, Kriemhildstr. 15, 44793 Bochum
^ 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