Merge branch 'maint'
authorShawn O. Pearce <spearce@spearce.org>
Sun, 21 Oct 2007 06:11:45 +0000 (02:11 -0400)
committerShawn O. Pearce <spearce@spearce.org>
Sun, 21 Oct 2007 06:11:45 +0000 (02:11 -0400)
* maint:
Describe more 1.5.3.5 fixes in release notes
Fix diffcore-break total breakage
Fix directory scanner to correctly ignore files without d_type
Improve receive-pack error message about funny ref creation
fast-import: Fix argument order to die in file_change_m
git-gui: Don't display CR within console windows
git-gui: Handle progress bars from newer gits
git-gui: Correctly report failures from git-write-tree
gitk.txt: Fix markup.
send-pack: respect '+' on wildcard refspecs
git-gui: accept versions containing text annotations, like 1.5.3.mingw.1
git-gui: Don't crash when starting gitk from a browser session
git-gui: Allow gitk to be started on Cygwin with native Tcl/Tk
git-gui: Ensure .git/info/exclude is honored in Cygwin workdirs
git-gui: Handle starting on mapped shares under Cygwin
git-gui: Display message box when we cannot find git in $PATH
git-gui: Avoid using bold text in entire gui for some fonts

13 files changed:
Documentation/RelNotes-1.5.3.5.txt
Documentation/gitk.txt
diffcore-break.c
dir.c
fast-import.c
git-gui/git-gui.sh
git-gui/lib/commit.tcl
git-gui/lib/console.tcl
git-gui/lib/status_bar.tcl
receive-pack.c
remote.c
t/t5400-send-pack.sh
tree-diff.c
index 49e52264ba23727bb329d746a973864454c3f1d2..9581e03c49eafa61f8d17b027395aa5613c9b27f 100644 (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
index e9f82b97b91b92785b76a224e176b695593cdbe7..8dbfb0d5a3ef015367e990f7c24d2a47b176fde4 100644 (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.
index ae8a7d03e2d103739897ac37fe1f9966956b9ec8..c71a22621a4f979f62cd21e9de83ab7129a129e9 100644 (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
diff --git a/dir.c b/dir.c
index eb6c3abd30baefb9501c69b0e956ae1231f4b085..f843c4dd208ac0f37f9c70383e522590688f1966 100644 (file)
--- a/dir.c
+++ b/dir.c
@@ -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++;
index e9c80be4cd3f2833dd227e3d2f3c69e2145935e2..6f888f64767ee78ef198180c6e628ddb60e09191 100644 (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)
index f789e91b66ae20b67103fb2d09758a9e99107b87..9335a9761b458f5e8d75abf342630672751c7f2a 100755 (executable)
@@ -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"
index f857a2ff5bb3d0e151ea471a16a1b233117afc70..57238129e420a313c34e2a99b9f9bdb87ecce39d 100644 (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
index 6f718fbac3277daed7d0d4e10c76241490c4c216..b038a783581d4fcc92b030669b8a8fb3c09a623e 100644 (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
                        }
index 72a8fe1fd36932efcb1e2f2e18e4200150436854..3bf79eb6e0608560d00aab82bc1d691db83881af 100644 (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
        }
 }
index d3c422be58c5ee1af7e75cf4186bc9bbfb19ec30..1521d0b2de77eaccf3db1ebf357fd7560b2de1b0 100644 (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";
        }
 
index bb774d0bcc3f5b3e7a8cdbb29ba43fcaf00f0d4c..cdbbdcb00dee400f4fe654a86c1dd0060a613904 100644 (file)
--- a/remote.c
+++ b/remote.c
@@ -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);
        }
index 57c6397be116bb93af2ccffb0cee2d4bb3901ca4..2d0c07fd6a38d786efc895bc5c5c0d7dd268b31f 100755 (executable)
@@ -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
index 26bdbdd2bfea5eab99b9f1c38936efe56f1ab45a..7c261fd7c3b38d2c2dbd722617c628d98848cbc1 100644 (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)