Merge commit 'mingw/master' into devel

This commit is contained in:
Steffen Prohaska
2008-04-06 17:51:11 +02:00
24 changed files with 765 additions and 127 deletions

View File

@@ -6,7 +6,7 @@ Updates since v1.5.4
(subsystems)
* Comes with git-gui 0.9.3.
* Comes with git-gui 0.10.0
(portability)
@@ -166,8 +166,8 @@ Updates since v1.5.4
symmetric difference between the HEAD version and the work tree version
of the submodule commits.
* Various "git cvsimport", "git cvsexportcommit", "git svn" and
"git p4" improvements.
* Various "git cvsimport", "git cvsexportcommit", "git cvsserver",
"git svn" and "git p4" improvements.
(internal)
@@ -208,6 +208,6 @@ this release, unless otherwise noted.
---
exec >/var/tmp/1
O=v1.5.5-rc1-21-g319a36a
O=v1.5.5-rc3
echo O=`git describe refs/heads/master`
git shortlog --no-merges $O..refs/heads/master ^refs/heads/maint

View File

@@ -661,6 +661,13 @@ gitcvs.dbuser, gitcvs.dbpass::
'gitcvs.dbuser' supports variable substitution (see
linkgit:git-cvsserver[1] for details).
gitcvs.dbTableNamePrefix::
Database table name prefix. Prepended to the names of any
database tables used, allowing a single database to be used
for several repositories. Supports variable substitution (see
linkgit:git-cvsserver[1] for details). Any non-alphabetic
characters will be replaced with underscores.
All gitcvs variables except for 'gitcvs.allbinary' can also be
specified as 'gitcvs.<access_method>.<varname>' (where 'access_method'
is one of "ext" and "pserver") to make them apply only for the given

View File

@@ -226,6 +226,12 @@ diff::
This lets you review what will be committed (i.e. between
HEAD and index).
Bugs
----
The interactive mode does not work with files whose names contain
characters that need C-quoting. `core.quotepath` configuration can be
used to work this limitation around to some degree, but backslash,
double-quote and control characters will still have problems.
See Also
--------

View File

@@ -227,6 +227,11 @@ gitcvs.dbpass::
Database password. Only useful if setting `dbdriver`, since
SQLite has no concept of database passwords.
gitcvs.dbTableNamePrefix::
Database table name prefix. Supports variable substitution
(see below). Any non-alphabetic characters will be replaced
with underscores.
All variables can also be set per access method, see <<configaccessmethod,above>>.
Variable substitution

View File

@@ -1,7 +1,7 @@
#!/bin/sh
GVF=GIT-VERSION-FILE
DEF_VER=v1.5.5-rc2.GIT
DEF_VER=v1.5.5-rc3.GIT
LF='
'

View File

@@ -46,8 +46,10 @@ static int run_gpg_verify(const char *buf, unsigned long size, int verbose)
gpg.argv = args_gpg;
gpg.in = -1;
args_gpg[2] = path;
if (start_command(&gpg))
if (start_command(&gpg)) {
unlink(path);
return error("could not run gpg.");
}
write_in_full(gpg.in, buf, len);
close(gpg.in);

View File

@@ -16,8 +16,11 @@ int git_vsnprintf(char *str, size_t maxsize, const char *format, va_list ap)
int ret;
ret = vsnprintf(str, maxsize-SNPRINTF_SIZE_CORR, format, ap);
if (ret != -1)
if (ret != -1) {
/* Windows does not NUL-terminate if result fits exactly */
str[ret] = 0;
return ret;
}
s = NULL;
if (maxsize < 128)

View File

@@ -999,7 +999,8 @@ _git_config ()
gitcvs.enabled
gitcvs.logfile
gitcvs.allbinary
gitcvs.dbname gitcvs.dbdriver gitcvs.dbuser gitcvs.dvpass
gitcvs.dbname gitcvs.dbdriver gitcvs.dbuser gitcvs.dbpass
gitcvs.dbtablenameprefix
gc.packrefs
gc.reflogexpire
gc.reflogexpireunreachable

View File

@@ -90,11 +90,11 @@ def getP4OpenedType(file):
# Returns the perforce file type for the given file.
result = read_pipe("p4 opened %s" % file)
match = re.match(".*\((.+)\)$", result)
match = re.match(".*\((.+)\)\r?$", result)
if match:
return match.group(1)
else:
die("Could not determine file type for %s" % file)
die("Could not determine file type for %s (result: '%s')" % (file, result))
def diffTreePattern():
# This is a simple generator for the diff tree regex pattern. This could be
@@ -513,6 +513,8 @@ class P4Submit(Command):
template = ""
inFilesSection = False
for line in read_pipe_lines("p4 change -o"):
if line.endswith("\r\n"):
line = line[:-2] + "\n"
if inFilesSection:
if line.startswith("\t"):
# path starts and ends with a tab
@@ -619,8 +621,6 @@ class P4Submit(Command):
setP4ExecBit(f, mode)
logMessage = extractLogMessageFromGitCommit(id)
if self.isWindows:
logMessage = logMessage.replace("\n", "\r\n")
logMessage = logMessage.strip()
template = self.prepareSubmitTemplate()
@@ -631,23 +631,25 @@ class P4Submit(Command):
del(os.environ["P4DIFF"])
diff = read_pipe("p4 diff -du ...")
newdiff = ""
for newFile in filesToAdd:
diff += "==== new file ====\n"
diff += "--- /dev/null\n"
diff += "+++ %s\n" % newFile
newdiff += "==== new file ====\n"
newdiff += "--- /dev/null\n"
newdiff += "+++ %s\n" % newFile
f = open(newFile, "r")
for line in f.readlines():
diff += "+" + line
newdiff += "+" + line
f.close()
separatorLine = "######## everything below this line is just the diff #######"
if platform.system() == "Windows":
separatorLine += "\r"
separatorLine += "\n"
separatorLine = "######## everything below this line is just the diff #######\n"
[handle, fileName] = tempfile.mkstemp()
tmpFile = os.fdopen(handle, "w+")
tmpFile.write(submitTemplate + separatorLine + diff)
if self.isWindows:
submitTemplate = submitTemplate.replace("\n", "\r\n")
separatorLine = separatorLine.replace("\n", "\r\n")
newdiff = newdiff.replace("\n", "\r\n")
tmpFile.write(submitTemplate + separatorLine + diff + newdiff)
tmpFile.close()
defaultEditor = "vi"
if platform.system() == "Windows":

View File

@@ -10,6 +10,7 @@
#include "cache-tree.h"
#include "path-list.h"
#include "unpack-trees.h"
#include "refs.h"
/*
* diff-files
@@ -333,6 +334,26 @@ int run_diff_files_cmd(struct rev_info *revs, int argc, const char **argv)
}
return run_diff_files(revs, options);
}
/*
* See if work tree has an entity that can be staged. Return 0 if so,
* return 1 if not and return -1 if error.
*/
static int check_work_tree_entity(const struct cache_entry *ce, struct stat *st, char *symcache)
{
if (lstat(ce->name, st) < 0) {
if (errno != ENOENT && errno != ENOTDIR)
return -1;
return 1;
}
if (has_symlink_leading_path(ce->name, symcache))
return 1;
if (S_ISDIR(st->st_mode)) {
unsigned char sub[20];
if (resolve_gitlink_ref(ce->name, "HEAD", sub))
return 1;
}
return 0;
}
int run_diff_files(struct rev_info *revs, unsigned int option)
{
@@ -341,10 +362,12 @@ int run_diff_files(struct rev_info *revs, unsigned int option)
int silent_on_removed = option & DIFF_SILENT_ON_REMOVED;
unsigned ce_option = ((option & DIFF_RACY_IS_MODIFIED)
? CE_MATCH_RACY_IS_DIRTY : 0);
char symcache[PATH_MAX];
if (diff_unmerged_stage < 0)
diff_unmerged_stage = 2;
entries = active_nr;
symcache[0] = '\0';
for (i = 0; i < entries; i++) {
struct stat st;
unsigned int oldmode, newmode;
@@ -376,16 +399,17 @@ int run_diff_files(struct rev_info *revs, unsigned int option)
memset(&(dpath->parent[0]), 0,
sizeof(struct combine_diff_parent)*5);
if (lstat(ce->name, &st) < 0) {
if (errno != ENOENT && errno != ENOTDIR) {
changed = check_work_tree_entity(ce, &st, symcache);
if (!changed)
dpath->mode = ce_mode_from_stat(ce, st.st_mode);
else {
if (changed < 0) {
perror(ce->name);
continue;
}
if (silent_on_removed)
continue;
}
else
dpath->mode = ce_mode_from_stat(ce, st.st_mode);
while (i < entries) {
struct cache_entry *nce = active_cache[i];
@@ -438,8 +462,10 @@ int run_diff_files(struct rev_info *revs, unsigned int option)
if (ce_uptodate(ce))
continue;
if (lstat(ce->name, &st) < 0) {
if (errno != ENOENT && errno != ENOTDIR) {
changed = check_work_tree_entity(ce, &st, symcache);
if (changed) {
if (changed < 0) {
perror(ce->name);
continue;
}
@@ -468,6 +494,11 @@ int run_diff_files(struct rev_info *revs, unsigned int option)
* diff-index
*/
struct oneway_unpack_data {
struct rev_info *revs;
char symcache[PATH_MAX];
};
/* A file entry went away or appeared */
static void diff_index_show_file(struct rev_info *revs,
const char *prefix,
@@ -481,7 +512,8 @@ static void diff_index_show_file(struct rev_info *revs,
static int get_stat_data(struct cache_entry *ce,
const unsigned char **sha1p,
unsigned int *modep,
int cached, int match_missing)
int cached, int match_missing,
struct oneway_unpack_data *cbdata)
{
const unsigned char *sha1 = ce->sha1;
unsigned int mode = ce->ce_mode;
@@ -489,8 +521,11 @@ static int get_stat_data(struct cache_entry *ce,
if (!cached) {
int changed;
struct stat st;
if (lstat(ce->name, &st) < 0) {
if (errno == ENOENT && match_missing) {
changed = check_work_tree_entity(ce, &st, cbdata->symcache);
if (changed < 0)
return -1;
else if (changed) {
if (match_missing) {
*sha1p = sha1;
*modep = mode;
return 0;
@@ -509,23 +544,25 @@ static int get_stat_data(struct cache_entry *ce,
return 0;
}
static void show_new_file(struct rev_info *revs,
static void show_new_file(struct oneway_unpack_data *cbdata,
struct cache_entry *new,
int cached, int match_missing)
{
const unsigned char *sha1;
unsigned int mode;
struct rev_info *revs = cbdata->revs;
/* New file in the index: it might actually be different in
/*
* New file in the index: it might actually be different in
* the working copy.
*/
if (get_stat_data(new, &sha1, &mode, cached, match_missing) < 0)
if (get_stat_data(new, &sha1, &mode, cached, match_missing, cbdata) < 0)
return;
diff_index_show_file(revs, "+", new, sha1, mode);
}
static int show_modified(struct rev_info *revs,
static int show_modified(struct oneway_unpack_data *cbdata,
struct cache_entry *old,
struct cache_entry *new,
int report_missing,
@@ -533,8 +570,9 @@ static int show_modified(struct rev_info *revs,
{
unsigned int mode, oldmode;
const unsigned char *sha1;
struct rev_info *revs = cbdata->revs;
if (get_stat_data(new, &sha1, &mode, cached, match_missing) < 0) {
if (get_stat_data(new, &sha1, &mode, cached, match_missing, cbdata) < 0) {
if (report_missing)
diff_index_show_file(revs, "-", old,
old->sha1, old->ce_mode);
@@ -602,7 +640,8 @@ static void do_oneway_diff(struct unpack_trees_options *o,
struct cache_entry *idx,
struct cache_entry *tree)
{
struct rev_info *revs = o->unpack_data;
struct oneway_unpack_data *cbdata = o->unpack_data;
struct rev_info *revs = cbdata->revs;
int match_missing, cached;
/*
@@ -625,7 +664,7 @@ static void do_oneway_diff(struct unpack_trees_options *o,
* Something added to the tree?
*/
if (!tree) {
show_new_file(revs, idx, cached, match_missing);
show_new_file(cbdata, idx, cached, match_missing);
return;
}
@@ -638,7 +677,7 @@ static void do_oneway_diff(struct unpack_trees_options *o,
}
/* Show difference between old and new */
show_modified(revs, tree, idx, 1, cached, match_missing);
show_modified(cbdata, tree, idx, 1, cached, match_missing);
}
static inline void skip_same_name(struct cache_entry *ce, struct unpack_trees_options *o)
@@ -675,7 +714,8 @@ static int oneway_diff(struct cache_entry **src, struct unpack_trees_options *o)
{
struct cache_entry *idx = src[0];
struct cache_entry *tree = src[1];
struct rev_info *revs = o->unpack_data;
struct oneway_unpack_data *cbdata = o->unpack_data;
struct rev_info *revs = cbdata->revs;
if (idx && ce_stage(idx))
skip_same_name(idx, o);
@@ -702,6 +742,7 @@ int run_diff_index(struct rev_info *revs, int cached)
const char *tree_name;
struct unpack_trees_options opts;
struct tree_desc t;
struct oneway_unpack_data unpack_cb;
mark_merge_entries();
@@ -711,12 +752,14 @@ int run_diff_index(struct rev_info *revs, int cached)
if (!tree)
return error("bad tree object %s", tree_name);
unpack_cb.revs = revs;
unpack_cb.symcache[0] = '\0';
memset(&opts, 0, sizeof(opts));
opts.head_idx = 1;
opts.index_only = cached;
opts.merge = 1;
opts.fn = oneway_diff;
opts.unpack_data = revs;
opts.unpack_data = &unpack_cb;
opts.src_index = &the_index;
opts.dst_index = NULL;
@@ -738,6 +781,7 @@ int do_diff_cache(const unsigned char *tree_sha1, struct diff_options *opt)
struct cache_entry *last = NULL;
struct unpack_trees_options opts;
struct tree_desc t;
struct oneway_unpack_data unpack_cb;
/*
* This is used by git-blame to run diff-cache internally;
@@ -766,12 +810,14 @@ int do_diff_cache(const unsigned char *tree_sha1, struct diff_options *opt)
if (!tree)
die("bad tree object %s", sha1_to_hex(tree_sha1));
unpack_cb.revs = &revs;
unpack_cb.symcache[0] = '\0';
memset(&opts, 0, sizeof(opts));
opts.head_idx = 1;
opts.index_only = 1;
opts.merge = 1;
opts.fn = oneway_diff;
opts.unpack_data = &revs;
opts.unpack_data = &unpack_cb;
opts.src_index = &the_index;
opts.dst_index = &the_index;

View File

@@ -360,6 +360,9 @@ yes)
mkdir -p "$GIT_DIR/objects/info"
echo "$repo/objects" >>"$GIT_DIR/objects/info/alternates"
else
cpio_quiet_flag=""
cpio --help 2>&1 | grep -- --quiet >/dev/null && \
cpio_quiet_flag=--quiet
l= &&
if test "$use_local_hardlink" = yes
then
@@ -380,7 +383,8 @@ yes)
fi
fi &&
cd "$repo" &&
find objects -depth -print | cpio -pumd$l "$GIT_DIR/" || exit 1
find objects -depth -print | cpio $cpio_quiet_flag -pumd$l "$GIT_DIR/" || \
exit 1
fi
git-ls-remote "$repo" >"$GIT_DIR/CLONE_HEAD" || exit 1
;;

View File

@@ -73,8 +73,8 @@ my $methods = {
'status' => \&req_status,
'admin' => \&req_CATCHALL,
'history' => \&req_CATCHALL,
'watchers' => \&req_CATCHALL,
'editors' => \&req_CATCHALL,
'watchers' => \&req_EMPTY,
'editors' => \&req_EMPTY,
'annotate' => \&req_annotate,
'Global_option' => \&req_Globaloption,
#'annotate' => \&req_CATCHALL,
@@ -199,6 +199,11 @@ sub req_CATCHALL
$log->warn("Unhandled command : req_$cmd : $data");
}
# This method invariably succeeds with an empty response.
sub req_EMPTY
{
print "ok\n";
}
# Root pathname \n
# Response expected: no. Tell the server which CVSROOT to use. Note that
@@ -958,6 +963,17 @@ sub req_update
$meta = $updater->getmeta($filename);
}
# If -p was given, "print" the contents of the requested revision.
if ( exists ( $state->{opt}{p} ) ) {
if ( defined ( $meta->{revision} ) ) {
$log->info("Printing '$filename' revision " . $meta->{revision});
transmitfile($meta->{filehash}, { print => 1 });
}
next;
}
if ( ! defined $meta )
{
$meta = {
@@ -1091,9 +1107,9 @@ sub req_update
my $file_local = $filepart . ".mine";
system("ln","-s",$state->{entries}{$filename}{modified_filename}, $file_local);
my $file_old = $filepart . "." . $oldmeta->{revision};
transmitfile($oldmeta->{filehash}, $file_old);
transmitfile($oldmeta->{filehash}, { targetfile => $file_old });
my $file_new = $filepart . "." . $meta->{revision};
transmitfile($meta->{filehash}, $file_new);
transmitfile($meta->{filehash}, { targetfile => $file_new });
# we need to merge with the local changes ( M=successful merge, C=conflict merge )
$log->info("Merging $file_local, $file_old, $file_new");
@@ -1423,6 +1439,8 @@ sub req_status
{
$filename = filecleanup($filename);
next if exists($state->{opt}{l}) && index($filename, '/', length($state->{prependdir})) >= 0;
my $meta = $updater->getmeta($filename);
my $oldmeta = $meta;
@@ -1466,8 +1484,10 @@ sub req_status
$status ||= "Unknown";
my ($filepart) = filenamesplit($filename);
print "M ===================================================================\n";
print "M File: $filename\tStatus: $status\n";
print "M File: $filepart\tStatus: $status\n";
if ( defined($state->{entries}{$filename}{revision}) )
{
print "M Working revision:\t" . $state->{entries}{$filename}{revision} . "\n";
@@ -1541,14 +1561,14 @@ sub req_diff
print "E File $filename at revision 1.$revision1 doesn't exist\n";
next;
}
transmitfile($meta1->{filehash}, $file1);
transmitfile($meta1->{filehash}, { targetfile => $file1 });
}
# otherwise we just use the working copy revision
else
{
( undef, $file1 ) = tempfile( DIR => $TEMP_DIR, OPEN => 0 );
$meta1 = $updater->getmeta($filename, $wrev);
transmitfile($meta1->{filehash}, $file1);
transmitfile($meta1->{filehash}, { targetfile => $file1 });
}
# if we have a second -r switch, use it too
@@ -1563,7 +1583,7 @@ sub req_diff
next;
}
transmitfile($meta2->{filehash}, $file2);
transmitfile($meta2->{filehash}, { targetfile => $file2 });
}
# otherwise we just use the working copy
else
@@ -1576,7 +1596,7 @@ sub req_diff
{
( undef, $file2 ) = tempfile( DIR => $TEMP_DIR, OPEN => 0 );
$meta2 = $updater->getmeta($filename, $wrev);
transmitfile($meta2->{filehash}, $file2);
transmitfile($meta2->{filehash}, { targetfile => $file2 });
}
# We need to have retrieved something useful
@@ -1708,8 +1728,7 @@ sub req_log
print "M revision 1.$revision->{revision}\n";
# reformat the date for log output
$revision->{modified} = sprintf('%04d/%02d/%02d %s', $3, $DATE_LIST->{$2}, $1, $4 ) if ( $revision->{modified} =~ /(\d+)\s+(\w+)\s+(\d+)\s+(\S+)/ and defined($DATE_LIST->{$2}) );
$revision->{author} =~ s/\s+.*//;
$revision->{author} =~ s/^(.{8}).*/$1/;
$revision->{author} = cvs_author($revision->{author});
print "M date: $revision->{modified}; author: $revision->{author}; state: " . ( $revision->{filehash} eq "deleted" ? "dead" : "Exp" ) . "; lines: +2 -3\n";
my $commitmessage = $updater->commitmessage($revision->{commithash});
$commitmessage =~ s/^/M /mg;
@@ -1824,8 +1843,7 @@ sub req_annotate
unless ( defined ( $metadata->{$commithash} ) )
{
$metadata->{$commithash} = $updater->getmeta($filename, $commithash);
$metadata->{$commithash}{author} =~ s/\s+.*//;
$metadata->{$commithash}{author} =~ s/^(.{8}).*/$1/;
$metadata->{$commithash}{author} = cvs_author($metadata->{$commithash}{author});
$metadata->{$commithash}{modified} = sprintf("%02d-%s-%02d", $1, $2, $3) if ( $metadata->{$commithash}{modified} =~ /^(\d+)\s(\w+)\s\d\d(\d\d)/ );
}
printf("M 1.%-5d (%-8s %10s): %s\n",
@@ -2005,14 +2023,17 @@ sub revparse
return undef;
}
# This method takes a file hash and does a CVS "file transfer" which transmits the
# size of the file, and then the file contents.
# If a second argument $targetfile is given, the file is instead written out to
# a file by the name of $targetfile
# This method takes a file hash and does a CVS "file transfer". Its
# exact behaviour depends on a second, optional hash table argument:
# - If $options->{targetfile}, dump the contents to that file;
# - If $options->{print}, use M/MT to transmit the contents one line
# at a time;
# - Otherwise, transmit the size of the file, followed by the file
# contents.
sub transmitfile
{
my $filehash = shift;
my $targetfile = shift;
my $options = shift;
if ( defined ( $filehash ) and $filehash eq "deleted" )
{
@@ -2034,11 +2055,20 @@ sub transmitfile
if ( open my $fh, '-|', "git-cat-file", "blob", $filehash )
{
if ( defined ( $targetfile ) )
if ( defined ( $options->{targetfile} ) )
{
my $targetfile = $options->{targetfile};
open NEWFILE, ">", $targetfile or die("Couldn't open '$targetfile' for writing : $!");
print NEWFILE $_ while ( <$fh> );
close NEWFILE or die("Failed to write '$targetfile': $!");
} elsif ( defined ( $options->{print} ) && $options->{print} ) {
while ( <$fh> ) {
if( /\n\z/ ) {
print 'M ', $_;
} else {
print 'MT text ', $_, "\n";
}
}
} else {
print "$size\n";
print while ( <$fh> );
@@ -2107,6 +2137,16 @@ sub kopts_from_path
}
}
# Generate a CVS author name from Git author information, by taking
# the first eight characters of the user part of the email address.
sub cvs_author
{
my $author_line = shift;
(my $author) = $author_line =~ /<([^>@]{1,8})/;
$author;
}
package GITCVS::log;
####
@@ -2311,6 +2351,14 @@ sub new
bless $self, $class;
$self->{valid_tables} = {'revision' => 1,
'revision_ix1' => 1,
'revision_ix2' => 1,
'head' => 1,
'head_ix1' => 1,
'properties' => 1,
'commitmsgs' => 1};
$self->{module} = $module;
$self->{git_path} = $config . "/";
@@ -2326,6 +2374,8 @@ sub new
$cfg->{gitcvs}{dbuser} || "";
$self->{dbpass} = $cfg->{gitcvs}{$state->{method}}{dbpass} ||
$cfg->{gitcvs}{dbpass} || "";
$self->{dbtablenameprefix} = $cfg->{gitcvs}{$state->{method}}{dbtablenameprefix} ||
$cfg->{gitcvs}{dbtablenameprefix} || "";
my %mapping = ( m => $module,
a => $state->{method},
u => getlogin || getpwuid($<) || $<,
@@ -2334,6 +2384,8 @@ sub new
);
$self->{dbname} =~ s/%([mauGg])/$mapping{$1}/eg;
$self->{dbuser} =~ s/%([mauGg])/$mapping{$1}/eg;
$self->{dbtablenameprefix} =~ s/%([mauGg])/$mapping{$1}/eg;
$self->{dbtablenameprefix} = mangle_tablename($self->{dbtablenameprefix});
die "Invalid char ':' in dbdriver" if $self->{dbdriver} =~ /:/;
die "Invalid char ';' in dbname" if $self->{dbname} =~ /;/;
@@ -2349,10 +2401,13 @@ sub new
}
# Construct the revision table if required
unless ( $self->{tables}{revision} )
unless ( $self->{tables}{$self->tablename("revision")} )
{
my $tablename = $self->tablename("revision");
my $ix1name = $self->tablename("revision_ix1");
my $ix2name = $self->tablename("revision_ix2");
$self->{dbh}->do("
CREATE TABLE revision (
CREATE TABLE $tablename (
name TEXT NOT NULL,
revision INTEGER NOT NULL,
filehash TEXT NOT NULL,
@@ -2363,20 +2418,22 @@ sub new
)
");
$self->{dbh}->do("
CREATE INDEX revision_ix1
ON revision (name,revision)
CREATE INDEX $ix1name
ON $tablename (name,revision)
");
$self->{dbh}->do("
CREATE INDEX revision_ix2
ON revision (name,commithash)
CREATE INDEX $ix2name
ON $tablename (name,commithash)
");
}
# Construct the head table if required
unless ( $self->{tables}{head} )
unless ( $self->{tables}{$self->tablename("head")} )
{
my $tablename = $self->tablename("head");
my $ix1name = $self->tablename("head_ix1");
$self->{dbh}->do("
CREATE TABLE head (
CREATE TABLE $tablename (
name TEXT NOT NULL,
revision INTEGER NOT NULL,
filehash TEXT NOT NULL,
@@ -2387,16 +2444,17 @@ sub new
)
");
$self->{dbh}->do("
CREATE INDEX head_ix1
ON head (name)
CREATE INDEX $ix1name
ON $tablename (name)
");
}
# Construct the properties table if required
unless ( $self->{tables}{properties} )
unless ( $self->{tables}{$self->tablename("properties")} )
{
my $tablename = $self->tablename("properties");
$self->{dbh}->do("
CREATE TABLE properties (
CREATE TABLE $tablename (
key TEXT NOT NULL PRIMARY KEY,
value TEXT
)
@@ -2404,10 +2462,11 @@ sub new
}
# Construct the commitmsgs table if required
unless ( $self->{tables}{commitmsgs} )
unless ( $self->{tables}{$self->tablename("commitmsgs")} )
{
my $tablename = $self->tablename("commitmsgs");
$self->{dbh}->do("
CREATE TABLE commitmsgs (
CREATE TABLE $tablename (
key TEXT NOT NULL PRIMARY KEY,
value TEXT
)
@@ -2417,6 +2476,21 @@ sub new
return $self;
}
=head2 tablename
=cut
sub tablename
{
my $self = shift;
my $name = shift;
if (exists $self->{valid_tables}{$name}) {
return $self->{dbtablenameprefix} . $name;
} else {
return undef;
}
}
=head2 update
=cut
@@ -2633,7 +2707,7 @@ sub update
};
$self->insert_rev($name, $head->{$name}{revision}, $hash, $commit->{hash}, $commit->{date}, $commit->{author}, $git_perms);
}
elsif ( $change eq "M" )
elsif ( $change eq "M" || $change eq "T" )
{
#$log->debug("MODIFIED $name");
$head->{$name} = {
@@ -2782,8 +2856,9 @@ sub insert_rev
my $modified = shift;
my $author = shift;
my $mode = shift;
my $tablename = $self->tablename("revision");
my $insert_rev = $self->{dbh}->prepare_cached("INSERT INTO revision (name, revision, filehash, commithash, modified, author, mode) VALUES (?,?,?,?,?,?,?)",{},1);
my $insert_rev = $self->{dbh}->prepare_cached("INSERT INTO $tablename (name, revision, filehash, commithash, modified, author, mode) VALUES (?,?,?,?,?,?,?)",{},1);
$insert_rev->execute($name, $revision, $filehash, $commithash, $modified, $author, $mode);
}
@@ -2792,16 +2867,18 @@ sub insert_mergelog
my $self = shift;
my $key = shift;
my $value = shift;
my $tablename = $self->tablename("commitmsgs");
my $insert_mergelog = $self->{dbh}->prepare_cached("INSERT INTO commitmsgs (key, value) VALUES (?,?)",{},1);
my $insert_mergelog = $self->{dbh}->prepare_cached("INSERT INTO $tablename (key, value) VALUES (?,?)",{},1);
$insert_mergelog->execute($key, $value);
}
sub delete_head
{
my $self = shift;
my $tablename = $self->tablename("head");
my $delete_head = $self->{dbh}->prepare_cached("DELETE FROM head",{},1);
my $delete_head = $self->{dbh}->prepare_cached("DELETE FROM $tablename",{},1);
$delete_head->execute();
}
@@ -2815,8 +2892,9 @@ sub insert_head
my $modified = shift;
my $author = shift;
my $mode = shift;
my $tablename = $self->tablename("head");
my $insert_head = $self->{dbh}->prepare_cached("INSERT INTO head (name, revision, filehash, commithash, modified, author, mode) VALUES (?,?,?,?,?,?,?)",{},1);
my $insert_head = $self->{dbh}->prepare_cached("INSERT INTO $tablename (name, revision, filehash, commithash, modified, author, mode) VALUES (?,?,?,?,?,?,?)",{},1);
$insert_head->execute($name, $revision, $filehash, $commithash, $modified, $author, $mode);
}
@@ -2824,8 +2902,9 @@ sub _headrev
{
my $self = shift;
my $filename = shift;
my $tablename = $self->tablename("head");
my $db_query = $self->{dbh}->prepare_cached("SELECT filehash, revision, mode FROM head WHERE name=?",{},1);
my $db_query = $self->{dbh}->prepare_cached("SELECT filehash, revision, mode FROM $tablename WHERE name=?",{},1);
$db_query->execute($filename);
my ( $hash, $revision, $mode ) = $db_query->fetchrow_array;
@@ -2836,8 +2915,9 @@ sub _get_prop
{
my $self = shift;
my $key = shift;
my $tablename = $self->tablename("properties");
my $db_query = $self->{dbh}->prepare_cached("SELECT value FROM properties WHERE key=?",{},1);
my $db_query = $self->{dbh}->prepare_cached("SELECT value FROM $tablename WHERE key=?",{},1);
$db_query->execute($key);
my ( $value ) = $db_query->fetchrow_array;
@@ -2849,13 +2929,14 @@ sub _set_prop
my $self = shift;
my $key = shift;
my $value = shift;
my $tablename = $self->tablename("properties");
my $db_query = $self->{dbh}->prepare_cached("UPDATE properties SET value=? WHERE key=?",{},1);
my $db_query = $self->{dbh}->prepare_cached("UPDATE $tablename SET value=? WHERE key=?",{},1);
$db_query->execute($value, $key);
unless ( $db_query->rows )
{
$db_query = $self->{dbh}->prepare_cached("INSERT INTO properties (key, value) VALUES (?,?)",{},1);
$db_query = $self->{dbh}->prepare_cached("INSERT INTO $tablename (key, value) VALUES (?,?)",{},1);
$db_query->execute($key, $value);
}
@@ -2869,10 +2950,11 @@ sub _set_prop
sub gethead
{
my $self = shift;
my $tablename = $self->tablename("head");
return $self->{gethead_cache} if ( defined ( $self->{gethead_cache} ) );
my $db_query = $self->{dbh}->prepare_cached("SELECT name, filehash, mode, revision, modified, commithash, author FROM head ORDER BY name ASC",{},1);
my $db_query = $self->{dbh}->prepare_cached("SELECT name, filehash, mode, revision, modified, commithash, author FROM $tablename ORDER BY name ASC",{},1);
$db_query->execute();
my $tree = [];
@@ -2894,8 +2976,9 @@ sub getlog
{
my $self = shift;
my $filename = shift;
my $tablename = $self->tablename("revision");
my $db_query = $self->{dbh}->prepare_cached("SELECT name, filehash, author, mode, revision, modified, commithash FROM revision WHERE name=? ORDER BY revision DESC",{},1);
my $db_query = $self->{dbh}->prepare_cached("SELECT name, filehash, author, mode, revision, modified, commithash FROM $tablename WHERE name=? ORDER BY revision DESC",{},1);
$db_query->execute($filename);
my $tree = [];
@@ -2919,19 +3002,21 @@ sub getmeta
my $self = shift;
my $filename = shift;
my $revision = shift;
my $tablename_rev = $self->tablename("revision");
my $tablename_head = $self->tablename("head");
my $db_query;
if ( defined($revision) and $revision =~ /^\d+$/ )
{
$db_query = $self->{dbh}->prepare_cached("SELECT * FROM revision WHERE name=? AND revision=?",{},1);
$db_query = $self->{dbh}->prepare_cached("SELECT * FROM $tablename_rev WHERE name=? AND revision=?",{},1);
$db_query->execute($filename, $revision);
}
elsif ( defined($revision) and $revision =~ /^[a-zA-Z0-9]{40}$/ )
{
$db_query = $self->{dbh}->prepare_cached("SELECT * FROM revision WHERE name=? AND commithash=?",{},1);
$db_query = $self->{dbh}->prepare_cached("SELECT * FROM $tablename_rev WHERE name=? AND commithash=?",{},1);
$db_query->execute($filename, $revision);
} else {
$db_query = $self->{dbh}->prepare_cached("SELECT * FROM head WHERE name=?",{},1);
$db_query = $self->{dbh}->prepare_cached("SELECT * FROM $tablename_head WHERE name=?",{},1);
$db_query->execute($filename);
}
@@ -2947,11 +3032,12 @@ sub commitmessage
{
my $self = shift;
my $commithash = shift;
my $tablename = $self->tablename("commitmsgs");
die("Need commithash") unless ( defined($commithash) and $commithash =~ /^[a-zA-Z0-9]{40}$/ );
my $db_query;
$db_query = $self->{dbh}->prepare_cached("SELECT value FROM commitmsgs WHERE key=?",{},1);
$db_query = $self->{dbh}->prepare_cached("SELECT value FROM $tablename WHERE key=?",{},1);
$db_query->execute($commithash);
my ( $message ) = $db_query->fetchrow_array;
@@ -2979,9 +3065,10 @@ sub gethistory
{
my $self = shift;
my $filename = shift;
my $tablename = $self->tablename("revision");
my $db_query;
$db_query = $self->{dbh}->prepare_cached("SELECT revision, filehash, commithash FROM revision WHERE name=? ORDER BY revision DESC",{},1);
$db_query = $self->{dbh}->prepare_cached("SELECT revision, filehash, commithash FROM $tablename WHERE name=? ORDER BY revision DESC",{},1);
$db_query->execute($filename);
return $db_query->fetchall_arrayref;
@@ -3001,9 +3088,10 @@ sub gethistorydense
{
my $self = shift;
my $filename = shift;
my $tablename = $self->tablename("revision");
my $db_query;
$db_query = $self->{dbh}->prepare_cached("SELECT revision, filehash, commithash FROM revision WHERE name=? AND filehash!='deleted' ORDER BY revision DESC",{},1);
$db_query = $self->{dbh}->prepare_cached("SELECT revision, filehash, commithash FROM $tablename WHERE name=? AND filehash!='deleted' ORDER BY revision DESC",{},1);
$db_query->execute($filename);
return $db_query->fetchall_arrayref;
@@ -3061,4 +3149,19 @@ sub mangle_dirname {
return $dirname;
}
=head2 mangle_tablename
create a string from a that is suitable to use as part of an SQL table
name, mainly by converting all chars except \w to _
=cut
sub mangle_tablename {
my $tablename = shift;
return unless defined $tablename;
$tablename =~ s/[^\w_]/_/g;
return $tablename;
}
1;

View File

@@ -281,7 +281,7 @@ while read commit parents; do
die "Could not checkout the index"
# files that $commit removed are now still in the working tree;
# remove them, else they would be added again
git clean -q -f -x
git clean -d -q -f -x
eval "$filter_tree" < /dev/null ||
die "tree filter failed: $filter_tree"

View File

@@ -1,7 +1,7 @@
#!/bin/sh
GVF=GIT-VERSION-FILE
DEF_VER=0.9.GITGUI
DEF_VER=0.10.GITGUI
LF='
'

View File

@@ -1846,6 +1846,22 @@ proc add_range_to_selection {w x y} {
$w tag add in_sel $begin.0 [expr {$end + 1}].0
}
proc show_more_context {} {
global repo_config
if {$repo_config(gui.diffcontext) < 99} {
incr repo_config(gui.diffcontext)
reshow_diff
}
}
proc show_less_context {} {
global repo_config
if {$repo_config(gui.diffcontext) >= 1} {
incr repo_config(gui.diffcontext) -1
reshow_diff
}
}
######################################################################
##
## ui construction
@@ -2046,6 +2062,16 @@ if {[is_enabled multicommit] || [is_enabled singlecommit]} {
.mbar.commit add separator
.mbar.commit add command -label [mc "Show Less Context"] \
-command show_less_context \
-accelerator $M1T-\[
.mbar.commit add command -label [mc "Show More Context"] \
-command show_more_context \
-accelerator $M1T-\]
.mbar.commit add separator
.mbar.commit add command -label [mc "Sign Off"] \
-command do_signoff \
-accelerator $M1T-S
@@ -2593,17 +2619,11 @@ lappend diff_actions [list $ctxm entryconf $ui_diff_applyhunk -state]
$ctxm add separator
$ctxm add command \
-label [mc "Show Less Context"] \
-command {if {$repo_config(gui.diffcontext) >= 1} {
incr repo_config(gui.diffcontext) -1
reshow_diff
}}
-command show_less_context
lappend diff_actions [list $ctxm entryconf [$ctxm index last] -state]
$ctxm add command \
-label [mc "Show More Context"] \
-command {if {$repo_config(gui.diffcontext) < 99} {
incr repo_config(gui.diffcontext)
reshow_diff
}}
-command show_more_context
lappend diff_actions [list $ctxm entryconf [$ctxm index last] -state]
$ctxm add separator
$ctxm add command \
@@ -2695,6 +2715,8 @@ bind $ui_comm <$M1B-Key-v> {tk_textPaste %W; %W see insert; break}
bind $ui_comm <$M1B-Key-V> {tk_textPaste %W; %W see insert; break}
bind $ui_comm <$M1B-Key-a> {%W tag add sel 0.0 end;break}
bind $ui_comm <$M1B-Key-A> {%W tag add sel 0.0 end;break}
bind $ui_comm <$M1B-Key-\[> {show_less_context;break}
bind $ui_comm <$M1B-Key-\]> {show_more_context;break}
bind $ui_diff <$M1B-Key-x> {tk_textCopy %W;break}
bind $ui_diff <$M1B-Key-X> {tk_textCopy %W;break}
@@ -2738,6 +2760,8 @@ bind . <$M1B-Key-t> do_add_selection
bind . <$M1B-Key-T> do_add_selection
bind . <$M1B-Key-i> do_add_all
bind . <$M1B-Key-I> do_add_all
bind . <$M1B-Key-\[> {show_less_context;break}
bind . <$M1B-Key-\]> {show_more_context;break}
bind . <$M1B-Key-Return> do_commit
foreach i [list $ui_index $ui_workdir] {
bind $i <Button-1> "toggle_or_diff $i %x %y; break"

View File

@@ -1900,7 +1900,7 @@ sub prop_walk {
foreach (sort keys %$dirent) {
next if $dirent->{$_}->{kind} != $SVN::Node::dir;
$self->prop_walk($path . '/' . $_, $rev, $sub);
$self->prop_walk($p . $_, $rev, $sub);
}
}

3
git.c
View File

@@ -148,8 +148,9 @@ static int handle_alias(int *argcp, const char ***argv)
const char** new_argv;
const char *alias_command;
char *alias_string;
int unused_nongit;
subdir = setup_git_directory_gently(NULL);
subdir = setup_git_directory_gently(&unused_nongit);
alias_command = (*argv)[0];
alias_string = alias_lookup(alias_command);

1
help.c
View File

@@ -35,6 +35,7 @@ static struct option builtin_help_options[] = {
HELP_FORMAT_WEB),
OPT_SET_INT('i', "info", &help_format, "show info page",
HELP_FORMAT_INFO),
OPT_END(),
};
static const char * const builtin_help_usage[] = {

60
mktag.c
View File

@@ -8,10 +8,11 @@
* message and a signature block that git itself doesn't care about,
* but that can be verified with gpg or similar.
*
* The first three lines are guaranteed to be at least 63 bytes:
* The first four lines are guaranteed to be at least 83 bytes:
* "object <sha1>\n" is 48 bytes, "type tag\n" at 9 bytes is the
* shortest possible type-line, and "tag .\n" at 6 bytes is the
* shortest single-character-tag line.
* shortest possible type-line, "tag .\n" at 6 bytes is the shortest
* single-character-tag line, and "tagger . <> 0 +0000\n" at 20 bytes is
* the shortest possible tagger-line.
*/
/*
@@ -43,9 +44,10 @@ static int verify_tag(char *buffer, unsigned long size)
int typelen;
char type[20];
unsigned char sha1[20];
const char *object, *type_line, *tag_line, *tagger_line;
const char *object, *type_line, *tag_line, *tagger_line, *lb, *rb;
size_t len;
if (size < 64)
if (size < 84)
return error("wanna fool me ? you obviously got the size wrong !");
buffer[size] = 0;
@@ -97,11 +99,51 @@ static int verify_tag(char *buffer, unsigned long size)
/* Verify the tagger line */
tagger_line = tag_line;
if (memcmp(tagger_line, "tagger", 6) || (tagger_line[6] == '\n'))
return error("char" PD_FMT ": could not find \"tagger\"", tagger_line - buffer);
if (memcmp(tagger_line, "tagger ", 7))
return error("char" PD_FMT ": could not find \"tagger \"",
tagger_line - buffer);
/* TODO: check for committer info + blank line? */
/* Also, the minimum length is probably + "tagger .", or 63+8=71 */
/*
* Check for correct form for name and email
* i.e. " <" followed by "> " on _this_ line
* No angle brackets within the name or email address fields.
* No spaces within the email address field.
*/
tagger_line += 7;
if (!(lb = strstr(tagger_line, " <")) || !(rb = strstr(lb+2, "> ")) ||
strpbrk(tagger_line, "<>\n") != lb+1 ||
strpbrk(lb+2, "><\n ") != rb)
return error("char" PD_FMT ": malformed tagger field",
tagger_line - buffer);
/* Check for author name, at least one character, space is acceptable */
if (lb == tagger_line)
return error("char" PD_FMT ": missing tagger name",
tagger_line - buffer);
/* timestamp, 1 or more digits followed by space */
tagger_line = rb + 2;
if (!(len = strspn(tagger_line, "0123456789")))
return error("char" PD_FMT ": missing tag timestamp",
tagger_line - buffer);
tagger_line += len;
if (*tagger_line != ' ')
return error("char" PD_FMT ": malformed tag timestamp",
tagger_line - buffer);
tagger_line++;
/* timezone, 5 digits [+-]hhmm, max. 1400 */
if (!((tagger_line[0] == '+' || tagger_line[0] == '-') &&
strspn(tagger_line+1, "0123456789") == 4 &&
tagger_line[5] == '\n' && atoi(tagger_line+1) <= 1400))
return error("char" PD_FMT ": malformed tag timezone",
tagger_line - buffer);
tagger_line += 6;
/* Verify the blank line separating the header from the body */
if (*tagger_line != '\n')
return error("char" PD_FMT ": trailing garbage in tag header",
tagger_line - buffer);
/* The actual stuff afterwards we don't care about.. */
return 0;

149
t/t2201-add-update-typechange.sh Executable file
View File

@@ -0,0 +1,149 @@
#!/bin/sh
test_description='more git add -u'
. ./test-lib.sh
symlink_change=T
if test "$no_symlinks"
then
ln () {
echo -n "$2" > "$3"
}
symlink_change=M
fi
_z40=0000000000000000000000000000000000000000
test_expect_success setup '
>xyzzy &&
_empty=$(git hash-object --stdin <xyzzy) &&
>yomin &&
>caskly &&
ln -s frotz nitfol &&
mkdir rezrov &&
>rezrov/bozbar &&
git add caskly xyzzy yomin nitfol rezrov/bozbar &&
test_tick &&
git commit -m initial
'
test_expect_success modify '
rm -f xyzzy yomin nitfol caskly &&
# caskly disappears (not a submodule)
mkdir caskly &&
# nitfol changes from symlink to regular
>nitfol &&
# rezrov/bozbar disappears
rm -fr rezrov &&
ln -s xyzzy rezrov &&
# xyzzy disappears (not a submodule)
mkdir xyzzy &&
echo gnusto >xyzzy/bozbar &&
# yomin gets replaced with a submodule
mkdir yomin &&
>yomin/yomin &&
(
cd yomin &&
git init &&
git add yomin &&
git commit -m "sub initial"
) &&
yomin=$(GIT_DIR=yomin/.git git rev-parse HEAD) &&
# yonk is added and then turned into a submodule
# this should appear as T in diff-files and as A in diff-index
>yonk &&
git add yonk &&
rm -f yonk &&
mkdir yonk &&
>yonk/yonk &&
(
cd yonk &&
git init &&
git add yonk &&
git commit -m "sub initial"
) &&
yonk=$(GIT_DIR=yonk/.git git rev-parse HEAD) &&
# zifmia is added and then removed
# this should appear in diff-files but not in diff-index.
>zifmia &&
git add zifmia &&
rm -f zifmia &&
mkdir zifmia &&
{
git ls-tree -r HEAD |
sed -e "s/^/:/" -e "
/ caskly/{
s/ caskly/ $_z40 D&/
s/blob/000000/
}
/ nitfol/{
s/ nitfol/ $_z40 $symlink_change&/
s/blob/100644/
}
/ rezrov.bozbar/{
s/ rezrov.bozbar/ $_z40 D&/
s/blob/000000/
}
/ xyzzy/{
s/ xyzzy/ $_z40 D&/
s/blob/000000/
}
/ yomin/{
s/ yomin/ $_z40 T&/
s/blob/160000/
}
"
} >expect &&
{
cat expect
echo ":100644 160000 $_empty $_z40 T yonk"
echo ":100644 000000 $_empty $_z40 D zifmia"
} >expect-files &&
{
cat expect
echo ":000000 160000 $_z40 $_z40 A yonk"
} >expect-index &&
{
echo "100644 $_empty 0 nitfol"
echo "160000 $yomin 0 yomin"
echo "160000 $yonk 0 yonk"
} >expect-final
'
test_expect_success diff-files '
git diff-files --raw >actual &&
diff -u expect-files actual
'
test_expect_success diff-index '
git diff-index --raw HEAD -- >actual &&
diff -u expect-index actual
'
test_expect_success 'add -u' '
rm -f ".git/saved-index" &&
cp -p ".git/index" ".git/saved-index" &&
git add -u &&
git ls-files -s >actual &&
diff -u expect-final actual
'
test_expect_success 'commit -a' '
if test -f ".git/saved-index"
then
rm -f ".git/index" &&
mv ".git/saved-index" ".git/index"
fi &&
git commit -m "second" -a &&
git ls-files -s >actual &&
diff -u expect-final actual &&
rm -f .git/index &&
git read-tree HEAD &&
git ls-files -s >actual &&
diff -u expect-final actual
'
test_done

View File

@@ -44,6 +44,8 @@ cat >tag.sig <<EOF
xxxxxx 139e9b33986b1c2670fff52c5067603117b3e895
type tag
tag mytag
tagger . <> 0 +0000
EOF
check_verify_failure '"object" line label check' '^error: char0: .*"object "$'
@@ -55,6 +57,8 @@ cat >tag.sig <<EOF
object zz9e9b33986b1c2670fff52c5067603117b3e895
type tag
tag mytag
tagger . <> 0 +0000
EOF
check_verify_failure '"object" line SHA1 check' '^error: char7: .*SHA1 hash$'
@@ -66,6 +70,8 @@ cat >tag.sig <<EOF
object 779e9b33986b1c2670fff52c5067603117b3e895
xxxx tag
tag mytag
tagger . <> 0 +0000
EOF
check_verify_failure '"type" line label check' '^error: char47: .*"\\ntype "$'
@@ -85,6 +91,8 @@ cat >tag.sig <<EOF
object 779e9b33986b1c2670fff52c5067603117b3e895
type tag
xxx mytag
tagger . <> 0 +0000
EOF
check_verify_failure '"tag" line label check #1' \
@@ -121,6 +129,8 @@ cat >tag.sig <<EOF
object 779e9b33986b1c2670fff52c5067603117b3e895
type tagggg
tag mytag
tagger . <> 0 +0000
EOF
check_verify_failure 'verify object (SHA1/type) check' \
@@ -133,6 +143,8 @@ cat >tag.sig <<EOF
object $head
type commit
tag my tag
tagger . <> 0 +0000
EOF
check_verify_failure 'verify tag-name check' \
@@ -145,10 +157,12 @@ cat >tag.sig <<EOF
object $head
type commit
tag mytag
This is filler
EOF
check_verify_failure '"tagger" line label check #1' \
'^error: char70: could not find "tagger"$'
'^error: char70: could not find "tagger "$'
############################################################
# 12. tagger line label check #2
@@ -158,19 +172,180 @@ object $head
type commit
tag mytag
tagger
This is filler
EOF
check_verify_failure '"tagger" line label check #2' \
'^error: char70: could not find "tagger"$'
'^error: char70: could not find "tagger "$'
############################################################
# 13. create valid tag
# 13. disallow missing tag author name
cat >tag.sig <<EOF
object $head
type commit
tag mytag
tagger another@example.com
tagger <> 0 +0000
This is filler
EOF
check_verify_failure 'disallow missing tag author name' \
'^error: char77: missing tagger name$'
############################################################
# 14. disallow missing tag author name
cat >tag.sig <<EOF
object $head
type commit
tag mytag
tagger T A Gger <
> 0 +0000
EOF
check_verify_failure 'disallow malformed tagger' \
'^error: char77: malformed tagger field$'
############################################################
# 15. allow empty tag email
cat >tag.sig <<EOF
object $head
type commit
tag mytag
tagger T A Gger <> 0 +0000
EOF
test_expect_success \
'allow empty tag email' \
'git-mktag <tag.sig >.git/refs/tags/mytag 2>message'
############################################################
# 16. disallow spaces in tag email
cat >tag.sig <<EOF
object $head
type commit
tag mytag
tagger T A Gger <tag ger@example.com> 0 +0000
EOF
check_verify_failure 'disallow spaces in tag email' \
'^error: char77: malformed tagger field$'
############################################################
# 17. disallow missing tag timestamp
cat >tag.sig <<EOF
object $head
type commit
tag mytag
tagger T A Gger <tagger@example.com>
EOF
check_verify_failure 'disallow missing tag timestamp' \
'^error: char107: missing tag timestamp$'
############################################################
# 18. detect invalid tag timestamp1
cat >tag.sig <<EOF
object $head
type commit
tag mytag
tagger T A Gger <tagger@example.com> Tue Mar 25 15:47:44 2008
EOF
check_verify_failure 'detect invalid tag timestamp1' \
'^error: char107: missing tag timestamp$'
############################################################
# 19. detect invalid tag timestamp2
cat >tag.sig <<EOF
object $head
type commit
tag mytag
tagger T A Gger <tagger@example.com> 2008-03-31T12:20:15-0500
EOF
check_verify_failure 'detect invalid tag timestamp2' \
'^error: char111: malformed tag timestamp$'
############################################################
# 20. detect invalid tag timezone1
cat >tag.sig <<EOF
object $head
type commit
tag mytag
tagger T A Gger <tagger@example.com> 1206478233 GMT
EOF
check_verify_failure 'detect invalid tag timezone1' \
'^error: char118: malformed tag timezone$'
############################################################
# 21. detect invalid tag timezone2
cat >tag.sig <<EOF
object $head
type commit
tag mytag
tagger T A Gger <tagger@example.com> 1206478233 + 30
EOF
check_verify_failure 'detect invalid tag timezone2' \
'^error: char118: malformed tag timezone$'
############################################################
# 22. detect invalid tag timezone3
cat >tag.sig <<EOF
object $head
type commit
tag mytag
tagger T A Gger <tagger@example.com> 1206478233 -1430
EOF
check_verify_failure 'detect invalid tag timezone3' \
'^error: char118: malformed tag timezone$'
############################################################
# 23. detect invalid header entry
cat >tag.sig <<EOF
object $head
type commit
tag mytag
tagger T A Gger <tagger@example.com> 1206478233 -0500
this line should not be here
EOF
check_verify_failure 'detect invalid header entry' \
'^error: char124: trailing garbage in tag header$'
############################################################
# 24. create valid tag
cat >tag.sig <<EOF
object $head
type commit
tag mytag
tagger T A Gger <tagger@example.com> 1206478233 -0500
EOF
test_expect_success \
@@ -178,7 +353,7 @@ test_expect_success \
'git-mktag <tag.sig >.git/refs/tags/mytag 2>message'
############################################################
# 14. check mytag
# 25. check mytag
test_expect_success \
'check mytag' \

View File

@@ -17,6 +17,8 @@ test_expect_success 'setup' '
make_commit B
git checkout -b branch B
make_commit D
mkdir dir
make_commit dir/D
make_commit E
git checkout master
make_commit C
@@ -41,9 +43,23 @@ test_expect_success 'rewrite, renaming a specific file' '
'
test_expect_success 'test that the file was renamed' '
test d = $(git show HEAD:doh) &&
test d = "$(git show HEAD:doh --)" &&
! test -f d &&
test -f doh &&
test d = $(cat doh)
test d = "$(cat doh)"
'
test_expect_success 'rewrite, renaming a specific directory' '
git-filter-branch -f --tree-filter "mv dir diroh || :" HEAD
'
test_expect_success 'test that the directory was renamed' '
test dir/d = "$(git show HEAD:diroh/d --)" &&
! test -d dir &&
test -d diroh &&
! test -d diroh/dir &&
test -f diroh/d &&
test dir/d = "$(cat diroh/d)"
'
git tag oldD HEAD~4

View File

@@ -579,6 +579,14 @@ test_expect_success \
git diff expect actual
'
# subsequent tests require gpg; check if it is available
gpg --version >/dev/null
if [ $? -eq 127 ]; then
echo "gpg not found - skipping tag signing and verification tests"
test_done
exit
fi
# trying to verify annotated non-signed tags:
test_expect_success \
@@ -601,13 +609,6 @@ test_expect_success \
# creating and verifying signed tags:
gpg --version >/dev/null
if [ $? -eq 127 ]; then
echo "Skipping signed tags tests, because gpg was not found"
test_done
exit
fi
# As said here: http://www.gnupg.org/documentation/faqs.html#q6.19
# the gpg version 1.0.6 didn't parse trust packets correctly, so for
# that version, creation of signed tags using the generated key fails.

View File

@@ -420,4 +420,54 @@ test_expect_success 'cvs update (merge no-op)' \
GIT_CONFIG="$git_config" cvs -Q update &&
diff -q merge ../merge'
cd "$WORKDIR"
test_expect_success 'cvs update (-p)' '
touch really-empty &&
echo Line 1 > no-lf &&
echo -n Line 2 >> no-lf &&
git add really-empty no-lf &&
git commit -q -m "Update -p test" &&
git push gitcvs.git >/dev/null &&
cd cvswork &&
GIT_CONFIG="$git_config" cvs update &&
rm -f failures &&
for i in merge no-lf empty really-empty; do
GIT_CONFIG="$git_config" cvs update -p "$i" >$i.out
diff $i.out ../$i >>failures 2>&1
done &&
test -z "$(cat failures)"
'
#------------
# CVS STATUS
#------------
cd "$WORKDIR"
test_expect_success 'cvs status' '
mkdir status.dir &&
echo Line > status.dir/status.file &&
echo Line > status.file &&
git add status.dir status.file &&
git commit -q -m "Status test" &&
git push gitcvs.git >/dev/null &&
cd cvswork &&
GIT_CONFIG="$git_config" cvs update &&
GIT_CONFIG="$git_config" cvs status | grep "^File: status.file" >../out &&
test $(wc -l <../out) = 2
'
cd "$WORKDIR"
test_expect_success 'cvs status (nonrecursive)' '
cd cvswork &&
GIT_CONFIG="$git_config" cvs status -l | grep "^File: status.file" >../out &&
test $(wc -l <../out) = 1
'
cd "$WORKDIR"
test_expect_success 'cvs status (no subdirs in header)' '
cd cvswork &&
GIT_CONFIG="$git_config" cvs status | grep ^File: >../out &&
! grep / <../out
'
test_done