mirror of
https://github.com/git/git.git
synced 2024-05-13 18:06:10 +02:00
cvsserver: generalize getmeta() to recognize commit refs
This allows getmeta() to recognize any commitish (sha1, tag/branch name, etc). Signed-off-by: Matthew Ogilvie <mmogilvi_git@miniinfo.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:
parent
eb5dcb2c02
commit
bfdafa099e
|
@ -4041,6 +4041,19 @@ =head2 getmeta
|
||||||
This function takes a filename (with path) argument and returns a hashref of
|
This function takes a filename (with path) argument and returns a hashref of
|
||||||
metadata for that file.
|
metadata for that file.
|
||||||
|
|
||||||
|
There are several ways $revision can be specified:
|
||||||
|
|
||||||
|
- A reference to hash that contains a "tag" that is the
|
||||||
|
actual revision (one of the below). TODO: Also allow it to
|
||||||
|
specify a "date" in the hash.
|
||||||
|
- undef, to refer to the latest version on the main branch.
|
||||||
|
- Full CVS client revision number (mapped to integer in DB, without the
|
||||||
|
"1." prefix),
|
||||||
|
- Complex CVS-compatible "special" revision number for
|
||||||
|
non-linear history (see comment below)
|
||||||
|
- git commit sha1 hash
|
||||||
|
- branch or tag name
|
||||||
|
|
||||||
=cut
|
=cut
|
||||||
|
|
||||||
sub getmeta
|
sub getmeta
|
||||||
|
@ -4051,23 +4064,144 @@ sub getmeta
|
||||||
my $tablename_rev = $self->tablename("revision");
|
my $tablename_rev = $self->tablename("revision");
|
||||||
my $tablename_head = $self->tablename("head");
|
my $tablename_head = $self->tablename("head");
|
||||||
|
|
||||||
my $db_query;
|
if ( ref($revision) eq "HASH" )
|
||||||
if ( defined($revision) and $revision =~ /^1\.(\d+)$/ )
|
|
||||||
{
|
{
|
||||||
my ($intRev) = $1;
|
$revision = $revision->{tag};
|
||||||
$db_query = $self->{dbh}->prepare_cached("SELECT * FROM $tablename_rev WHERE name=? AND revision=?",{},1);
|
}
|
||||||
$db_query->execute($filename, $intRev);
|
|
||||||
}
|
# Overview of CVS revision numbers:
|
||||||
elsif ( defined($revision) and $revision =~ /^[a-zA-Z0-9]{40}$/ )
|
#
|
||||||
{
|
# General CVS numbering scheme:
|
||||||
$db_query = $self->{dbh}->prepare_cached("SELECT * FROM $tablename_rev WHERE name=? AND commithash=?",{},1);
|
# - Basic mainline branch numbers: "1.1", "1.2", "1.3", etc.
|
||||||
$db_query->execute($filename, $revision);
|
# - Result of "cvs checkin -r" (possible, but not really
|
||||||
} else {
|
# recommended): "2.1", "2.2", etc
|
||||||
$db_query = $self->{dbh}->prepare_cached("SELECT * FROM $tablename_head WHERE name=?",{},1);
|
# - Branch tag: "1.2.0.n", where "1.2" is revision it was branched
|
||||||
$db_query->execute($filename);
|
# from, "0" is a magic placeholder that identifies it as a
|
||||||
|
# branch tag instead of a version tag, and n is 2 times the
|
||||||
|
# branch number off of "1.2", starting with "2".
|
||||||
|
# - Version on a branch: "1.2.n.x", where "1.2" is branch-from, "n"
|
||||||
|
# is branch number off of "1.2" (like n above), and "x" is
|
||||||
|
# the version number on the branch.
|
||||||
|
# - Branches can branch off of branches: "1.3.2.7.4.1" (even number
|
||||||
|
# of components).
|
||||||
|
# - Odd "n"s are used by "vendor branches" that result
|
||||||
|
# from "cvs import". Vendor branches have additional
|
||||||
|
# strangeness in the sense that the main rcs "head" of the main
|
||||||
|
# branch will (temporarily until first normal commit) point
|
||||||
|
# to the version on the vendor branch, rather than the actual
|
||||||
|
# main branch. (FUTURE: This may provide an opportunity
|
||||||
|
# to use "strange" revision numbers for fast-forward-merged
|
||||||
|
# branch tip when CVS client is asking for the main branch.)
|
||||||
|
#
|
||||||
|
# git-cvsserver CVS-compatible special numbering schemes:
|
||||||
|
# - Currently git-cvsserver only tries to be identical to CVS for
|
||||||
|
# simple "1.x" numbers on the "main" branch (as identified
|
||||||
|
# by the module name that was originally cvs checkout'ed).
|
||||||
|
# - The database only stores the "x" part, for historical reasons.
|
||||||
|
# But most of the rest of the cvsserver preserves
|
||||||
|
# and thinks using the full revision number.
|
||||||
|
# - To handle non-linear history, it uses a version of the form
|
||||||
|
# "2.1.1.2000.b.b.b."..., where the 2.1.1.2000 is to help uniquely
|
||||||
|
# identify this as a special revision number, and there are
|
||||||
|
# 20 b's that together encode the sha1 git commit from which
|
||||||
|
# this version of this file originated. Each b is
|
||||||
|
# the numerical value of the corresponding byte plus
|
||||||
|
# 100.
|
||||||
|
# - "plus 100" avoids "0"s, and also reduces the
|
||||||
|
# likelyhood of a collision in the case that someone someday
|
||||||
|
# writes an import tool that tries to preserve original
|
||||||
|
# CVS revision numbers, and the original CVS data had done
|
||||||
|
# lots of branches off of branches and other strangeness to
|
||||||
|
# end up with a real version number that just happens to look
|
||||||
|
# like this special revision number form. Also, if needed
|
||||||
|
# there are several ways to extend/identify alternative encodings
|
||||||
|
# within the "2.1.1.2000" part if necessary.
|
||||||
|
# - Unlike real CVS revisions, you can't really reconstruct what
|
||||||
|
# relation a revision of this form has to other revisions.
|
||||||
|
# - FUTURE: TODO: Rework database somehow to make up and remember
|
||||||
|
# fully-CVS-compatible branches and branch version numbers.
|
||||||
|
|
||||||
|
my $meta;
|
||||||
|
if ( defined($revision) )
|
||||||
|
{
|
||||||
|
if ( $revision =~ /^1\.(\d+)$/ )
|
||||||
|
{
|
||||||
|
my ($intRev) = $1;
|
||||||
|
my $db_query;
|
||||||
|
$db_query = $self->{dbh}->prepare_cached(
|
||||||
|
"SELECT * FROM $tablename_rev WHERE name=? AND revision=?",
|
||||||
|
{},1);
|
||||||
|
$db_query->execute($filename, $intRev);
|
||||||
|
$meta = $db_query->fetchrow_hashref;
|
||||||
|
}
|
||||||
|
elsif ( $revision =~ /^2\.1\.1\.2000(\.[1-3][0-9][0-9]){20}$/ )
|
||||||
|
{
|
||||||
|
my ($commitHash)=($revision=~/^2\.1\.1\.2000(.*)$/);
|
||||||
|
$commitHash=~s/\.([0-9]+)/sprintf("%02x",$1-100)/eg;
|
||||||
|
if($commitHash=~/^[0-9a-f]{40}$/)
|
||||||
|
{
|
||||||
|
return $self->getMetaFromCommithash($filename,$commitHash);
|
||||||
|
}
|
||||||
|
|
||||||
|
# error recovery: fall back on head version below
|
||||||
|
print "E Failed to find $filename version=$revision or commit=$commitHash\n";
|
||||||
|
$log->warning("failed get $revision with commithash=$commitHash");
|
||||||
|
undef $revision;
|
||||||
|
}
|
||||||
|
elsif ( $revision =~ /^[0-9a-f]{40}$/ )
|
||||||
|
{
|
||||||
|
# Try DB first. This is mostly only useful for req_annotate(),
|
||||||
|
# which only calls this for stuff that should already be in
|
||||||
|
# the DB. It is fairly likely to be a waste of time
|
||||||
|
# in most other cases [unless the file happened to be
|
||||||
|
# modified in $revision specifically], but
|
||||||
|
# it is probably in the noise compared to how long
|
||||||
|
# getMetaFromCommithash() will take.
|
||||||
|
my $db_query;
|
||||||
|
$db_query = $self->{dbh}->prepare_cached(
|
||||||
|
"SELECT * FROM $tablename_rev WHERE name=? AND commithash=?",
|
||||||
|
{},1);
|
||||||
|
$db_query->execute($filename, $revision);
|
||||||
|
$meta = $db_query->fetchrow_hashref;
|
||||||
|
|
||||||
|
if(! $meta)
|
||||||
|
{
|
||||||
|
my($revCommit)=$self->lookupCommitRef($revision);
|
||||||
|
if($revCommit=~/^[0-9a-f]{40}$/)
|
||||||
|
{
|
||||||
|
return $self->getMetaFromCommithash($filename,$revCommit);
|
||||||
|
}
|
||||||
|
|
||||||
|
# error recovery: nothing found:
|
||||||
|
print "E Failed to find $filename version=$revision\n";
|
||||||
|
$log->warning("failed get $revision");
|
||||||
|
return $meta;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
my($revCommit)=$self->lookupCommitRef($revision);
|
||||||
|
if($revCommit=~/^[0-9a-f]{40}$/)
|
||||||
|
{
|
||||||
|
return $self->getMetaFromCommithash($filename,$revCommit);
|
||||||
|
}
|
||||||
|
|
||||||
|
# error recovery: fall back on head version below
|
||||||
|
print "E Failed to find $filename version=$revision\n";
|
||||||
|
$log->warning("failed get $revision");
|
||||||
|
undef $revision; # Allow fallback
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!defined($revision))
|
||||||
|
{
|
||||||
|
my $db_query;
|
||||||
|
$db_query = $self->{dbh}->prepare_cached(
|
||||||
|
"SELECT * FROM $tablename_head WHERE name=?",{},1);
|
||||||
|
$db_query->execute($filename);
|
||||||
|
$meta = $db_query->fetchrow_hashref;
|
||||||
}
|
}
|
||||||
|
|
||||||
my $meta = $db_query->fetchrow_hashref;
|
|
||||||
if($meta)
|
if($meta)
|
||||||
{
|
{
|
||||||
$meta->{revision} = "1.$meta->{revision}";
|
$meta->{revision} = "1.$meta->{revision}";
|
||||||
|
|
Loading…
Reference in New Issue