Merge branch 'master' of git://repo.or.cz/git/spearce

This commit is contained in:
Johannes Sixt
2007-10-22 14:06:49 +02:00
20 changed files with 231 additions and 60 deletions

View File

@@ -4,6 +4,8 @@ GIT v1.5.3.5 Release Notes
Fixes since v1.5.3.4
--------------------
* Comes with git-gui 0.8.4.
* "git-config" silently ignored options after --list; now it will
error out with a usage message.
@@ -27,12 +29,20 @@ Fixes since v1.5.3.4
* "git-log --follow" did not work unless diff generation (e.g. -p)
was also requested.
* "git-log --follow -B" did not work at all. Fixed.
* "git-log -M -B" did not correctly handle cases of very large files
being renamed and replaced by very small files in the same commit.
* "git-log" printed extra newlines between commits when a diff
was generated internally (e.g. -S or --follow) but not displayed.
* "git-push" error message is more helpful when pushing to a
repository with no matching refs and none specified.
* "git-push" now respects + (force push) on wildcard refspecs,
matching the behavior of git-fetch.
* "git-filter-branch" now updates the working directory when it
has finished filtering the current branch.
@@ -46,6 +56,11 @@ Fixes since v1.5.3.4
not impact correctness, only user perception. The bogus error
is no longer printed.
* "git-ls-files --ignored" did not properly descend into non-ignored
directories that themselves contained ignored files if d_type
was not supported by the filesystem. This bug impacted systems
such as AFS. Fixed.
* Git segfaulted when reading an invalid .gitattributes file. Fixed.
* post-receive-email example hook fixed was fixed for

View File

@@ -69,7 +69,7 @@ gitk --since="2 weeks ago" \-- gitk::
The "--" is necessary to avoid confusion with the *branch* named
'gitk'
gitk --max-count=100 --all -- Makefile::
gitk --max-count=100 --all \-- Makefile::
Show at most 100 changes made to the file 'Makefile'. Instead of only
looking for changes in the current branch look in all branches.

View File

@@ -25,7 +25,7 @@ static int update_ref_env(const char *action,
unsigned char *oldval)
{
char msg[1024];
char *rla = getenv("GIT_REFLOG_ACTION");
const char *rla = getenv("GIT_REFLOG_ACTION");
if (!rla)
rla = "(reflog update)";
@@ -61,7 +61,7 @@ static int update_local_ref(const char *name,
}
if (get_sha1(name, sha1_old)) {
char *msg;
const char *msg;
just_store:
/* new ref */
if (!strncmp(name, "refs/tags/", 10))

View File

@@ -288,7 +288,7 @@ static void cleanup_space(char *buf)
}
static void decode_header(char *it, unsigned itsize);
static char *header[MAX_HDR_PARSED] = {
static const char *header[MAX_HDR_PARSED] = {
"From","Subject","Date",
};

View File

@@ -169,7 +169,7 @@ static void prepend_reflog_action(const char *action, char *buf, size_t size)
}
enum reset_type { MIXED, SOFT, HARD, NONE };
static char *reset_type_names[] = { "mixed", "soft", "hard", NULL };
static const char *reset_type_names[] = { "mixed", "soft", "hard", NULL };
int cmd_reset(int argc, const char **argv, const char *prefix)
{

View File

@@ -399,6 +399,7 @@ class P4Submit(Command):
optparse.make_option("--dry-run", action="store_true"),
optparse.make_option("--direct", dest="directSubmit", action="store_true"),
optparse.make_option("--trust-me-like-a-fool", dest="trustMeLikeAFool", action="store_true"),
optparse.make_option("-M", dest="detectRename", action="store_true"),
]
self.description = "Submit changes from git to the perforce depot."
self.usage += " [name of git branch to submit into perforce depot]"
@@ -411,6 +412,7 @@ class P4Submit(Command):
self.origin = ""
self.directSubmit = False
self.trustMeLikeAFool = False
self.detectRename = False
self.verbose = False
self.isWindows = (platform.system() == "Windows")
@@ -491,7 +493,8 @@ class P4Submit(Command):
diff = self.diffStatus
else:
print "Applying %s" % (read_pipe("git log --max-count=1 --pretty=oneline %s" % id))
diff = read_pipe_lines("git diff-tree -r --name-status \"%s^\" \"%s\"" % (id, id))
diffOpts = ("", "-M")[self.detectRename]
diff = read_pipe_lines("git diff-tree -r --name-status %s \"%s^\" \"%s\"" % (diffOpts, id, id))
filesToAdd = set()
filesToDelete = set()
editedFiles = set()
@@ -509,6 +512,13 @@ class P4Submit(Command):
filesToDelete.add(path)
if path in filesToAdd:
filesToAdd.remove(path)
elif modifier == "R":
src, dest = line.strip().split("\t")[1:3]
system("p4 integrate -Dt \"%s\" \"%s\"" % (src, dest))
system("p4 edit \"%s\"" % (dest))
os.unlink(dest)
editedFiles.add(dest)
filesToDelete.add(src)
else:
die("unknown modifier %s for %s" % (modifier, path))
@@ -529,6 +539,10 @@ class P4Submit(Command):
"and with .rej files / [w]rite the patch to a file (patch.txt) ")
if response == "s":
print "Skipping! Good luck with the next patches..."
for f in editedFiles:
system("p4 revert \"%s\"" % f);
for f in filesToAdd:
system("rm %s" %f)
return
elif response == "a":
os.system(applyPatchCmd)

View File

@@ -45,8 +45,8 @@ static int should_break(struct diff_filespec *src,
* The value we return is 1 if we want the pair to be broken,
* or 0 if we do not.
*/
unsigned long delta_size, base_size, src_copied, literal_added,
src_removed;
unsigned long delta_size, base_size, max_size;
unsigned long src_copied, literal_added, src_removed;
*merge_score_p = 0; /* assume no deletion --- "do not break"
* is the default.
@@ -63,7 +63,8 @@ static int should_break(struct diff_filespec *src,
return 0; /* error but caught downstream */
base_size = ((src->size < dst->size) ? src->size : dst->size);
if (base_size < MINIMUM_BREAK_SIZE)
max_size = ((src->size > dst->size) ? src->size : dst->size);
if (max_size < MINIMUM_BREAK_SIZE)
return 0; /* we do not break too small filepair */
if (diffcore_count_changes(src, dst,
@@ -89,12 +90,14 @@ static int should_break(struct diff_filespec *src,
* less than the minimum, after rename/copy runs.
*/
*merge_score_p = (int)(src_removed * MAX_SCORE / src->size);
if (*merge_score_p > break_score)
return 1;
/* Extent of damage, which counts both inserts and
* deletes.
*/
delta_size = src_removed + literal_added;
if (delta_size * MAX_SCORE / base_size < break_score)
if (delta_size * MAX_SCORE / max_size < break_score)
return 0;
/* If you removed a lot without adding new material, that is

52
dir.c
View File

@@ -443,6 +443,24 @@ static int in_pathspec(const char *path, int len, const struct path_simplify *si
return 0;
}
static int get_dtype(struct dirent *de, const char *path)
{
int dtype = DTYPE(de);
struct stat st;
if (dtype != DT_UNKNOWN)
return dtype;
if (lstat(path, &st))
return dtype;
if (S_ISREG(st.st_mode))
return DT_REG;
if (S_ISDIR(st.st_mode))
return DT_DIR;
if (S_ISLNK(st.st_mode))
return DT_LNK;
return dtype;
}
/*
* Read a directory tree. We currently ignore anything but
* directories, regular files and symlinks. That's because git
@@ -466,7 +484,7 @@ static int read_directory_recursive(struct dir_struct *dir, const char *path, co
exclude_stk = push_exclude_per_directory(dir, base, baselen);
while ((de = readdir(fdir)) != NULL) {
int len;
int len, dtype;
int exclude;
if ((de->d_name[0] == '.') &&
@@ -486,24 +504,30 @@ static int read_directory_recursive(struct dir_struct *dir, const char *path, co
if (exclude && dir->collect_ignored
&& in_pathspec(fullname, baselen + len, simplify))
dir_add_ignored(dir, fullname, baselen + len);
if (exclude != dir->show_ignored) {
if (!dir->show_ignored || DTYPE(de) != DT_DIR) {
/*
* Excluded? If we don't explicitly want to show
* ignored files, ignore it
*/
if (exclude && !dir->show_ignored)
continue;
dtype = get_dtype(de, fullname);
/*
* Do we want to see just the ignored files?
* We still need to recurse into directories,
* even if we don't ignore them, since the
* directory may contain files that we do..
*/
if (!exclude && dir->show_ignored) {
if (dtype != DT_DIR)
continue;
}
}
switch (DTYPE(de)) {
struct stat st;
switch (dtype) {
default:
continue;
case DT_UNKNOWN:
if (lstat(fullname, &st))
continue;
if (S_ISREG(st.st_mode) || S_ISLNK(st.st_mode))
break;
if (!S_ISDIR(st.st_mode))
continue;
/* fallthrough */
case DT_DIR:
memcpy(fullname + baselen + len, "/", 2);
len++;

View File

@@ -1817,7 +1817,7 @@ static void file_change_m(struct branch *b)
} else if (oe) {
if (oe->type != OBJ_BLOB)
die("Not a blob (actually a %s): %s",
command_buf.buf, typename(oe->type));
typename(oe->type), command_buf.buf);
} else {
enum object_type type = sha1_object_info(sha1, NULL);
if (type < 0)

View File

@@ -305,7 +305,7 @@ proc _which {what} {
global env _search_exe _search_path
if {$_search_path eq {}} {
if {[is_Cygwin]} {
if {[is_Cygwin] && [regexp {^(/|\.:)} $env(PATH)]} {
set _search_path [split [exec cygpath \
--windows \
--path \
@@ -498,7 +498,11 @@ proc rmsel_tag {text} {
set _git [_which git]
if {$_git eq {}} {
catch {wm withdraw .}
error_popup "Cannot find git in PATH."
tk_messageBox \
-icon error \
-type ok \
-title [mc "git-gui: fatal error"] \
-message [mc "Cannot find git in PATH."]
exit 1
}
@@ -534,6 +538,7 @@ regsub -- {-dirty$} $_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
regsub {\.[a-zA-Z]+\.[0-9]+$} $_git_version {} _git_version
if {![regexp {^[1-9]+(\.[0-9]+)+$} $_git_version]} {
catch {wm withdraw .}
@@ -903,6 +908,35 @@ proc rescan {after {honor_trustmtime 1}} {
}
}
if {[is_Cygwin]} {
set is_git_info_link {}
set is_git_info_exclude {}
proc have_info_exclude {} {
global is_git_info_link is_git_info_exclude
if {$is_git_info_link eq {}} {
set is_git_info_link [file isfile [gitdir info.lnk]]
}
if {$is_git_info_link} {
if {$is_git_info_exclude eq {}} {
if {[catch {exec test -f [gitdir info exclude]}]} {
set is_git_info_exclude 0
} else {
set is_git_info_exclude 1
}
}
return $is_git_info_exclude
} else {
return [file readable [gitdir info exclude]]
}
}
} else {
proc have_info_exclude {} {
return [file readable [gitdir info exclude]]
}
}
proc rescan_stage2 {fd after} {
global rescan_active buf_rdi buf_rdf buf_rlo
@@ -913,9 +947,8 @@ proc rescan_stage2 {fd after} {
}
set ls_others [list --exclude-per-directory=.gitignore]
set info_exclude [gitdir info exclude]
if {[file readable $info_exclude]} {
lappend ls_others "--exclude-from=$info_exclude"
if {[have_info_exclude]} {
lappend ls_others "--exclude-from=[gitdir info exclude]"
}
set user_exclude [get_config core.excludesfile]
if {$user_exclude ne {} && [file readable $user_exclude]} {
@@ -1093,11 +1126,17 @@ proc mapdesc {state path} {
}
proc ui_status {msg} {
$::main_status show $msg
global main_status
if {[info exists main_status]} {
$main_status show $msg
}
}
proc ui_ready {{test {}}} {
$::main_status show {Ready.} $test
global main_status
if {[info exists main_status]} {
$main_status show [mc "Ready."] $test
}
}
proc escape_path {path} {
@@ -1436,7 +1475,27 @@ proc do_gitk {revs} {
if {! [file exists $exe]} {
error_popup "Unable to start gitk:\n\n$exe does not exist"
} else {
global env
if {[info exists env(GIT_DIR)]} {
set old_GIT_DIR $env(GIT_DIR)
} else {
set old_GIT_DIR {}
}
set pwd [pwd]
cd [file dirname [gitdir]]
set env(GIT_DIR) [file tail [gitdir]]
eval exec $cmd $revs &
if {$old_GIT_DIR eq {}} {
unset env(GIT_DIR)
} else {
set env(GIT_DIR) $old_GIT_DIR
}
cd $pwd
ui_status $::starting_gitk_msg
after 10000 {
ui_ready $starting_gitk_msg
@@ -1648,7 +1707,7 @@ proc apply_config {} {
set font [lindex $option 1]
if {[catch {
foreach {cn cv} $repo_config(gui.$name) {
font configure $font $cn $cv
font configure $font $cn $cv -weight normal
}
} err]} {
error_popup "Invalid font specified in gui.$name:\n\n$err"

View File

@@ -253,7 +253,7 @@ proc commit_committree {fd_wt curHEAD msg} {
global repo_config
gets $fd_wt tree_id
if {$tree_id eq {} || [catch {close $fd_wt} err]} {
if {[catch {close $fd_wt} err]} {
error_popup "write-tree failed:\n\n$err"
ui_status {Commit failed.}
unlock_index

View File

@@ -122,7 +122,7 @@ method _read {fd after} {
} else {
$w.m.t delete $console_cr end
$w.m.t insert end "\n"
$w.m.t insert end [string range $buf $c $cr]
$w.m.t insert end [string range $buf $c [expr {$cr - 1}]]
set c $cr
incr c
}

View File

@@ -69,7 +69,10 @@ method update_meter {buf} {
set prior [string range $meter 0 $r]
set meter [string range $meter [expr {$r + 1}] end]
if {[regexp "\\((\\d+)/(\\d+)\\)\\s+done\r\$" $prior _j a b]} {
set p "\\((\\d+)/(\\d+)\\)"
if {[regexp ":\\s*\\d+% $p\(?:, done.\\s*\n|\\s*\r)\$" $prior _j a b]} {
update $this $a $b
} elseif {[regexp "$p\\s+done\r\$" $prior _j a b]} {
update $this $a $b
}
}

5
git.c
View File

@@ -422,8 +422,7 @@ int main(int argc, const char **argv)
/*
* Take the basename of argv[0] as the command
* name, and the dirname as the default exec_path
* if it's an absolute path and we don't have
* anything better.
* if we don't have anything better.
*/
#ifdef __MINGW32__
if (!slash)
@@ -433,6 +432,8 @@ int main(int argc, const char **argv)
*slash++ = 0;
if (is_absolute_path(cmd))
exec_path = cmd;
else
exec_path = xstrdup(make_absolute_path(cmd));
cmd = slash;
}

41
gitk
View File

@@ -92,7 +92,7 @@ proc start_rev_list {view} {
set order "--date-order"
}
if {[catch {
set fd [open [concat | git log -z --pretty=raw $order --parents \
set fd [open [concat | git log --no-color -z --pretty=raw $order --parents \
--boundary $viewargs($view) "--" $viewfiles($view)] r]
} err]} {
error_popup "Error executing git rev-list: $err"
@@ -843,6 +843,12 @@ proc makewindow {} {
} else {
bindall <ButtonRelease-4> "allcanvs yview scroll -5 units"
bindall <ButtonRelease-5> "allcanvs yview scroll 5 units"
if {[tk windowingsystem] eq "aqua"} {
bindall <MouseWheel> {
set delta [expr {- (%D)}]
allcanvs yview scroll $delta units
}
}
}
bindall <2> "canvscan mark %W %x %y"
bindall <B2-Motion> "canvscan dragto %W %x %y"
@@ -3690,34 +3696,23 @@ proc drawcommits {row {endrow {}}} {
drawcmitrow $r
if {$r == $er} break
set nextid [lindex $displayorder [expr {$r + 1}]]
if {$wasdrawn && [info exists iddrawn($nextid)]} {
catch {unset prevlines}
continue
}
if {$wasdrawn && [info exists iddrawn($nextid)]} continue
drawparentlinks $id $r
if {[info exists lineends($r)]} {
foreach lid $lineends($r) {
unset prevlines($lid)
}
}
set rowids [lindex $rowidlist $r]
foreach lid $rowids {
if {$lid eq {}} continue
if {[info exists lineend($lid)] && $lineend($lid) > $r} continue
if {$lid eq $id} {
# see if this is the first child of any of its parents
foreach p [lindex $parentlist $r] {
if {[lsearch -exact $rowids $p] < 0} {
# make this line extend up to the child
set le [drawlineseg $p $r $er 0]
lappend lineends($le) $p
set prevlines($p) 1
set lineend($p) [drawlineseg $p $r $er 0]
}
}
} elseif {![info exists prevlines($lid)]} {
set le [drawlineseg $lid $r $er 1]
lappend lineends($le) $lid
set prevlines($lid) 1
} else {
set lineend($lid) [drawlineseg $lid $r $er 1]
}
}
}
@@ -5216,8 +5211,7 @@ proc getblobdiffline {bdf ids} {
set diffinhdr 0
} elseif {$diffinhdr} {
if {![string compare -length 12 "rename from " $line] ||
![string compare -length 10 "copy from " $line]} {
if {![string compare -length 12 "rename from " $line]} {
set fname [string range $line [expr 6 + [string first " from " $line] ] end]
if {[string index $fname 0] eq "\""} {
set fname [lindex $fname 0]
@@ -6644,7 +6638,7 @@ proc addnewchild {id p} {
global arcnos arcids arctags arcout arcend arcstart archeads growing
global seeds allcommits
if {![info exists allcommits]} return
if {![info exists allcommits] || ![info exists arcnos($p)]} return
lappend allids $id
set allparents($id) [list $p]
set allchildren($id) {}
@@ -7834,6 +7828,13 @@ proc tcl_encoding {enc} {
return {}
}
# First check that Tcl/Tk is recent enough
if {[catch {package require Tk 8.4} err]} {
show_error {} . "Sorry, gitk cannot run with this version of Tcl/Tk.\n\
Gitk requires at least Tcl/Tk 8.4."
exit 1
}
# defaults...
set datemode 0
set diffopts "-U 5 -p"

View File

@@ -132,7 +132,7 @@ static void match_trees(const unsigned char *hash1,
const unsigned char *hash2,
int *best_score,
char **best_match,
char *base,
const char *base,
int recurse_limit)
{
struct tree_desc one;

View File

@@ -166,7 +166,7 @@ static const char *update(struct command *cmd)
struct ref_lock *lock;
if (!prefixcmp(name, "refs/") && check_ref_format(name + 5)) {
error("refusing to create funny ref '%s' locally", name);
error("refusing to create funny ref '%s' remotely", name);
return "funny refname";
}

View File

@@ -626,6 +626,8 @@ int match_refs(struct ref *src, struct ref *dst, struct ref ***dst_tail,
hashcpy(dst_peer->new_sha1, src->new_sha1);
}
dst_peer->peer_ref = src;
if (pat)
dst_peer->force = pat->force;
free_name:
free(dst_name);
}

View File

@@ -123,4 +123,52 @@ test_expect_success \
git-branch -a >branches && ! grep -q origin/master branches
'
rewound_push_setup() {
rm -rf parent child &&
mkdir parent && cd parent &&
git-init && echo one >file && git-add file && git-commit -m one &&
echo two >file && git-commit -a -m two &&
cd .. &&
git-clone parent child && cd child && git-reset --hard HEAD^
}
rewound_push_succeeded() {
cmp ../parent/.git/refs/heads/master .git/refs/heads/master
}
rewound_push_failed() {
if rewound_push_succeeded
then
false
else
true
fi
}
test_expect_success \
'pushing explicit refspecs respects forcing' '
rewound_push_setup &&
if git-send-pack ../parent/.git refs/heads/master:refs/heads/master
then
false
else
true
fi && rewound_push_failed &&
git-send-pack ../parent/.git +refs/heads/master:refs/heads/master &&
rewound_push_succeeded
'
test_expect_success \
'pushing wildcard refspecs respects forcing' '
rewound_push_setup &&
if git-send-pack ../parent/.git refs/heads/*:refs/heads/*
then
false
else
true
fi && rewound_push_failed &&
git-send-pack ../parent/.git +refs/heads/*:refs/heads/* &&
rewound_push_succeeded
'
test_done

View File

@@ -319,6 +319,7 @@ static void try_to_follow_renames(struct tree_desc *t1, struct tree_desc *t2, co
diff_opts.detect_rename = DIFF_DETECT_RENAME;
diff_opts.output_format = DIFF_FORMAT_NO_OUTPUT;
diff_opts.single_follow = opt->paths[0];
diff_opts.break_opt = opt->break_opt;
paths[0] = NULL;
diff_tree_setup_paths(paths, &diff_opts);
if (diff_setup_done(&diff_opts) < 0)