Gitweb snapshot of subdirectory

The calling URL will http://<gitweburl>/gitweb.cgi?p=<repo>;a=tree;f=<subdir>;hb=HEAD

display a tree <repo>

starting at <subdir>

.

The calling url http://<gitweburl>/gitweb.cgi?p=<repo>;a=snapshot;f=<subdir>;hb=HEAD

will produce a 404.

The calling URL http://<gitweburl>/gitweb.cgi?p=<repo>.git;a=snapshot;h=HEAD

will provide a snapshot <repo>

in the HEAD revision.

I can't seem to find the correct syntax to get Gitweb to give a snapshot starting from a subdirectory. I mean something leading to:$ git archive --format=tar --remote=<gituser>@<gitserver>:<repo> HEAD:<subdir>

I was naively trying to call the url http://<gitweburl>/gitweb.cgi?p=<repo>;a=snapshot;h=HEAD;f=<subdir>

but that results in a snapshot archive containing the entire repository .

After clicking on the Gitweb web interface, I found out that by going to the "tree" view and navigating to <subdir>

, and then clicking "snapshot", use a URL similar to this one:

http://<gitweburl>?p=<repo>;a=snapshot;h=42a6503da6aaedc92bb3543e0b0de9b2de0aaae9;sf=tgz

Which provides exactly what I want, but I have no idea what this hash parameter is h=...

. This is not a commit id - I checked. He has to define in some way <subdir>

. But even if it does - it still doesn't help me because someone just wants a snapshot starting with / containing only <subdir>

usually doesn't know this hash.

Any idea on how to get a snapshot of a subdirectory via Gitweb? Thanks in advance!


Addition:

Just figured out: h=42a6503da6aaedc92bb3543e0b0de9b2de0aaae9

is the hash value associated with <subdir>

, visible for example.$ git ls-tree -r -t HEAD

So these two commands:

$ git archive --format=tar --remote=<gituser>@<gitserver>:<repo> HEAD:<subdir>

$ git archive --format=tar --remote=<gituser>@<gitserver>:<repo> 42a6503da6aaedc92bb3543e0b0de9b2de0aaae9

doing the same thing, which makes me think that HEAD:<subdir>

and are 42a6503da6aaedc92bb3543e0b0de9b2de0aaae9

equivalent. However, I cannot simply replace the hash in http://<gitweburl>?p=<repo>;a=snapshot;h=42a6503da6aaedc92bb3543e0b0de9b2de0aaae9;sf=tgz

with HEAD:<subdir>

. Calling that url results in "400 - Invalid hash parameter" ... so no real progress here.


As suggested by poke, a quick dirty hack to use URL http://<gitweburl>/gitweb.cgi?p=<repo>;a=snapshot;h=HEAD;f=<subdir>

$ diff -Naur gitweb.cgi.original gitweb.cgi.new 
--- gitweb.cgi.original 2012-09-28 00:50:47.000000000 +0200
+++ gitweb.cgi.new  2013-01-22 11:04:29.870532502 +0100
@@ -7029,6 +7029,9 @@

    my ($name, $prefix) = snapshot_name($project, $hash);
    my $filename = "$name$known_snapshot_formats{$format}{'suffix'}";
+   if ($file_name) {
+       $hash="$hash:$file_name"
+   }
    my $cmd = quote_command(
        git_cmd(), 'archive',
        "--format=$known_snapshot_formats{$format}{'format'}",

      

+3


source to share


2 answers


The value h

is the identifier of the tree object you are currently looking at. The end has one root tree object, which you can see on the Gitwebs commit page. And each tree is a list of directory entries pointing to blobs (in the case of files) or other tree objects.

So when you move deeper into the tree, it h

always represents the tree ID. On the other hand, the value hb

is the commit ID.



Unfortunately, Gitweb does not provide a better way to get a snapshot of a subdirectory, i.e. without knowing the tree hash, just for the path. But it is probably possible to add some functions to it that take the parameter into account f

and automatically get the hash of the head for you.

I just checked the source for this and you might be happy to change this part . I don't know perl very well to tell you exactly what to do, but you can basically check if a variable is set $file_name

, and if so, just get a hash for $hash:$file_name

. Then you set this to a new hash and everything can work.

+2


source


I recently ran into a similar task - to have gitweb create an archive with object names (only one f = URL argument is allowed, but we can pass% 20 spaces to list multiple objects). Here is my general patch against gitweb.cgi as in OpenSuse 13.2 "git-web-2.1.4-13.1.x86_64".

Feel free to use and enjoy:

--- gitweb.cgi.orig     2015-03-13 13:42:29.000000000 +0100
+++ gitweb.cgi.snapshot-filenames-withoutDebug  2015-07-02 14:50:46.196000000 +0200
@@ -20,6 +20,11 @@
 use Time::HiRes qw(gettimeofday tv_interval);
 binmode STDOUT, ':utf8';

+# http://www.spinics.net/lists/git/msg241958.html
+if (!defined($CGI::VERSION) || $CGI::VERSION < 4.08) {
+       eval 'sub CGI::multi_param { CGI::param(@_) }'
+}
+
 our $t0 = [ gettimeofday() ];
 our $number_of_git_cmds = 0;

@@ -871,7 +876,7 @@

        while (my ($name, $symbol) = each %cgi_param_mapping) {
                if ($symbol eq 'opt') {
-                       $input_params{$name} = [ map { decode_utf8($_) } $cgi->param($symbol) ];
+                       $input_params{$name} = [ map { decode_utf8($_) } $cgi->multi_param($symbol) ];
                } else {
                        $input_params{$name} = decode_utf8($cgi->param($symbol));
                }
@@ -7324,6 +7329,15 @@
                die_error(403, "Unsupported snapshot format");
        }

+       if (!defined($hash)) {
+               $hash = "";
+               if ( $file_name && $file_name =~ /^([^:]*):(.*)$/ ) {
+                       $hash = "$1";
+                       $file_name = "$2";
+               }
+               if ( $hash eq "") { $hash = "HEAD"; }
+               printf STDERR "Defaulted hash to '$hash' ('h=' URL argument was missing)\n";
+       }
        my $type = git_get_type("$hash^{}");
        if (!$type) {
                die_error(404, 'Object does not exist');
@@ -7341,6 +7354,14 @@
                git_cmd(), 'archive',
                "--format=$known_snapshot_formats{$format}{'format'}",
                "--prefix=$prefix/", $hash);
+       if ($file_name) {
+               # To fetch several pathnames use space-separation, e.g.
+               # "...git-web?p=proj.git;a=snapshot;f=file1%20file2
+               # To fetch pathnames with spaces, escape them, e.g.
+               # "...git-web?p=proj.git;a=snapshot;f=file\%20name
+               $cmd .= " " . $file_name;
+       }
+
        if (exists $known_snapshot_formats{$format}{'compressor'}) {
                $cmd .= ' | ' . quote_command(@{$known_snapshot_formats{$format}{'compressor'}});
        }

      



UPDATE: This drop in code has been revisited and extended with unit testing, etc. and PR'ed against upstream gitweb ... let's see how it goes;) More details here: https://github.com/git/git/pull/206

Hope this helps, Jim Klimov

0


source







All Articles