Merge branch 'jn/editor-pager'
authorJunio C Hamano <gitster@pobox.com>
Sat, 21 Nov 2009 07:48:52 +0000 (23:48 -0800)
committerJunio C Hamano <gitster@pobox.com>
Sat, 21 Nov 2009 07:48:52 +0000 (23:48 -0800)
* jn/editor-pager:
Provide a build time default-pager setting
Provide a build time default-editor setting
am -i, git-svn: use "git var GIT_PAGER"
add -i, send-email, svn, p4, etc: use "git var GIT_EDITOR"
Teach git var about GIT_PAGER
Teach git var about GIT_EDITOR
Suppress warnings from "git var -l"
Do not use VISUAL editor on dumb terminals
Handle more shell metacharacters in editor names

1  2 
Documentation/config.txt
Makefile
cache.h
git-add--interactive.perl
git-svn.perl
diff --combined Documentation/config.txt
index cb73d7571f25deffb061441577ce1ae531fdf5d9,5181b7762946b011bff51c152393631f72d5d294..c9b8db5cf701fa39fc518dd196c4acfb57cac0c4
@@@ -387,9 -387,7 +387,7 @@@ core.editor:
        Commands such as `commit` and `tag` that lets you edit
        messages by launching an editor uses the value of this
        variable when it is set, and the environment variable
-       `GIT_EDITOR` is not set.  The order of preference is
-       `GIT_EDITOR` environment, `core.editor`, `VISUAL` and
-       `EDITOR` environment variables and then finally `vi`.
+       `GIT_EDITOR` is not set.  See linkgit:git-var[1].
  
  core.pager::
        The command that git will use to paginate output.  Can
@@@ -1360,7 -1358,7 +1358,7 @@@ receive.denyCurrentBranch:
  
  receive.denyNonFastForwards::
        If set to true, git-receive-pack will deny a ref update which is
 -      not a fast forward. Use this to prevent such an update via a push,
 +      not a fast-forward. Use this to prevent such an update via a push,
        even if that push is forced. This configuration variable is
        set when initializing a shared repository.
  
diff --combined Makefile
index 4e596dcd0bfe01c2d325a02ac5d7b39b67df2912,18fc50a37bfaa781ec5a12574f585ec0e25cda45..f8906618e89bfa0e06fccea8280bae2a4e53d84f
+++ b/Makefile
@@@ -159,10 -159,6 +159,10 @@@ all:
  # Define ASCIIDOC_NO_ROFF if your DocBook XSL escapes raw roff directives
  # (versions 1.72 and later and 1.68.1 and earlier).
  #
 +# Define GNU_ROFF if your target system uses GNU groff.  This forces
 +# apostrophes to be ASCII so that cut&pasting examples to the shell
 +# will work.
 +#
  # Define NO_PERL_MAKEMAKER if you cannot use Makefiles generated by perl's
  # MakeMaker (e.g. using ActiveState under Cygwin).
  #
  # memory allocators with the nedmalloc allocator written by Niall Douglas.
  #
  # Define NO_REGEX if you have no or inferior regex support in your C library.
+ #
+ # Define DEFAULT_PAGER to a sensible pager command (defaults to "less") if
+ # you want to use something different.  The value will be interpreted by the
+ # shell at runtime when it is used.
+ #
+ # Define DEFAULT_EDITOR to a sensible editor command (defaults to "vi") if you
+ # want to use something different.  The value will be interpreted by the shell
+ # if necessary when it is used.  Examples:
+ #
+ #   DEFAULT_EDITOR='~/bin/vi',
+ #   DEFAULT_EDITOR='$GIT_FALLBACK_EDITOR',
+ #   DEFAULT_EDITOR='"C:\Program Files\Vim\gvim.exe" --nofork'
  
  GIT-VERSION-FILE: .FORCE-GIT-VERSION-FILE
        @$(SHELL_PATH) ./GIT-VERSION-GEN
@@@ -216,12 -224,6 +228,12 @@@ uname_R := $(shell sh -c 'uname -r 2>/d
  uname_P := $(shell sh -c 'uname -p 2>/dev/null || echo not')
  uname_V := $(shell sh -c 'uname -v 2>/dev/null || echo not')
  
 +ifdef MSVC
 +      # avoid the MingW and Cygwin configuration sections
 +      uname_S := Windows
 +      uname_O := Windows
 +endif
 +
  # CFLAGS and LDFLAGS are for the users to override from the command line.
  
  CFLAGS = -g -O2 -Wall
@@@ -364,7 -366,6 +376,7 @@@ EXTRA_PROGRAMS 
  PROGRAMS += $(EXTRA_PROGRAMS)
  PROGRAMS += git-fast-import$X
  PROGRAMS += git-hash-object$X
 +PROGRAMS += git-imap-send$X
  PROGRAMS += git-index-pack$X
  PROGRAMS += git-merge-index$X
  PROGRAMS += git-merge-tree$X
@@@ -423,7 -424,6 +435,7 @@@ LIB_H += builtin.
  LIB_H += cache.h
  LIB_H += cache-tree.h
  LIB_H += commit.h
 +LIB_H += compat/bswap.h
  LIB_H += compat/cygwin.h
  LIB_H += compat/mingw.h
  LIB_H += csum-file.h
@@@ -464,7 -464,6 +476,7 @@@ LIB_H += sideband.
  LIB_H += sigchain.h
  LIB_H += strbuf.h
  LIB_H += string-list.h
 +LIB_H += submodule.h
  LIB_H += tag.h
  LIB_H += transport.h
  LIB_H += tree.h
@@@ -563,7 -562,6 +575,7 @@@ LIB_OBJS += sideband.
  LIB_OBJS += sigchain.o
  LIB_OBJS += strbuf.o
  LIB_OBJS += string-list.o
 +LIB_OBJS += submodule.o
  LIB_OBJS += symlinks.o
  LIB_OBJS += tag.o
  LIB_OBJS += trace.o
@@@ -608,6 -606,7 +620,6 @@@ BUILTIN_OBJS += builtin-diff-index.
  BUILTIN_OBJS += builtin-diff-tree.o
  BUILTIN_OBJS += builtin-diff.o
  BUILTIN_OBJS += builtin-fast-export.o
 -BUILTIN_OBJS += builtin-fetch--tool.o
  BUILTIN_OBJS += builtin-fetch-pack.o
  BUILTIN_OBJS += builtin-fetch.o
  BUILTIN_OBJS += builtin-fmt-merge-msg.o
@@@ -795,8 -794,6 +807,8 @@@ ifeq ($(uname_O),Cygwin
        NO_MMAP = YesPlease
        NO_IPV6 = YesPlease
        X = .exe
 +      COMPAT_OBJS += compat/cygwin.o
 +      UNRELIABLE_FSTAT = UnfortunatelyYes
  endif
  ifeq ($(uname_S),FreeBSD)
        NEEDS_LIBICONV = YesPlease
@@@ -906,11 -903,15 +918,11 @@@ ifeq ($(uname_S),HP-UX
        NO_SYS_SELECT_H = YesPlease
        SNPRINTF_RETURNS_BOGUS = YesPlease
  endif
 -ifneq (,$(findstring CYGWIN,$(uname_S)))
 -      COMPAT_OBJS += compat/cygwin.o
 -      UNRELIABLE_FSTAT = UnfortunatelyYes
 -endif
 -ifdef MSVC
 +ifeq ($(uname_S),Windows)
        GIT_VERSION := $(GIT_VERSION).MSVC
        pathsep = ;
        NO_PREAD = YesPlease
 -      NO_OPENSSL = YesPlease
 +      NEEDS_CRYPTO_WITH_SSL = YesPlease
        NO_LIBGEN_H = YesPlease
        NO_SYMLINK_HEAD = YesPlease
        NO_IPV6 = YesPlease
        NO_REGEX = YesPlease
        NO_CURL = YesPlease
        NO_PTHREADS = YesPlease
 +      BLK_SHA1 = YesPlease
  
        CC = compat/vcbuild/scripts/clink.pl
        AR = compat/vcbuild/scripts/lib.pl
@@@ -959,11 -959,11 +971,11 @@@ els
        BASIC_CFLAGS += -Zi -MTd
  endif
        X = .exe
 -else
 +endif
  ifneq (,$(findstring MINGW,$(uname_S)))
        pathsep = ;
        NO_PREAD = YesPlease
 -      NO_OPENSSL = YesPlease
 +      NEEDS_CRYPTO_WITH_SSL = YesPlease
        NO_LIBGEN_H = YesPlease
        NO_SYMLINK_HEAD = YesPlease
        NO_IPV6 = YesPlease
        UNRELIABLE_FSTAT = UnfortunatelyYes
        OBJECT_CREATION_USES_RENAMES = UnfortunatelyNeedsTo
        NO_REGEX = YesPlease
 +      BLK_SHA1 = YesPlease
        COMPAT_CFLAGS += -D__USE_MINGW_ACCESS -DNOGDI -Icompat -Icompat/fnmatch
        COMPAT_CFLAGS += -DSTRIP_EXTENSION=\".exe\"
        COMPAT_OBJS += compat/mingw.o compat/fnmatch/fnmatch.o compat/winansi.o
@@@ -1009,6 -1008,7 +1021,6 @@@ els
        NO_PTHREADS = YesPlease
  endif
  endif
 -endif
  
  -include config.mak.autogen
  -include config.mak
@@@ -1087,6 -1087,7 +1099,6 @@@ EXTLIBS += -l
  
  ifndef NO_POSIX_ONLY_PROGRAMS
        PROGRAMS += git-daemon$X
 -      PROGRAMS += git-imap-send$X
  endif
  ifndef NO_OPENSSL
        OPENSSL_LIBSSL = -lssl
@@@ -1374,6 -1375,22 +1386,22 @@@ BASIC_CFLAGS += -DSHA1_HEADER='$(SHA1_H
        $(COMPAT_CFLAGS)
  LIB_OBJS += $(COMPAT_OBJS)
  
+ # Quote for C
+ ifdef DEFAULT_EDITOR
+ DEFAULT_EDITOR_CQ = "$(subst ",\",$(subst \,\\,$(DEFAULT_EDITOR)))"
+ DEFAULT_EDITOR_CQ_SQ = $(subst ','\'',$(DEFAULT_EDITOR_CQ))
+ BASIC_CFLAGS += -DDEFAULT_EDITOR='$(DEFAULT_EDITOR_CQ_SQ)'
+ endif
+ ifdef DEFAULT_PAGER
+ DEFAULT_PAGER_CQ = "$(subst ",\",$(subst \,\\,$(DEFAULT_PAGER)))"
+ DEFAULT_PAGER_CQ_SQ = $(subst ','\'',$(DEFAULT_PAGER_CQ))
+ BASIC_CFLAGS += -DDEFAULT_PAGER='$(DEFAULT_PAGER_CQ_SQ)'
+ endif
  ALL_CFLAGS += $(BASIC_CFLAGS)
  ALL_LDFLAGS += $(BASIC_LDFLAGS)
  
@@@ -1810,10 -1827,7 +1838,10 @@@ dist: git.spec git-archive$(X) configur
        gzip -f -9 $(GIT_TARNAME).tar
  
  rpm: dist
 -      $(RPMBUILD) -ta $(GIT_TARNAME).tar.gz
 +      $(RPMBUILD) \
 +              --define "_source_filedigest_algorithm md5" \
 +              --define "_binary_filedigest_algorithm md5" \
 +              -ta $(GIT_TARNAME).tar.gz
  
  htmldocs = git-htmldocs-$(GIT_VERSION)
  manpages = git-manpages-$(GIT_VERSION)
diff --combined cache.h
index 71a731dbc988a8a22d0a2e1f8f3a5223f4c5d67a,5aaa4bac98e1ccba7426b2003f2488b7e41b346b..a9047491e650dc0f6267b578fabeb33cafd20885
+++ b/cache.h
@@@ -396,7 -396,6 +396,7 @@@ extern const char *setup_git_directory_
  extern const char *setup_git_directory(void);
  extern const char *prefix_path(const char *prefix, int len, const char *path);
  extern const char *prefix_filename(const char *prefix, int len, const char *path);
 +extern int check_filename(const char *prefix, const char *name);
  extern void verify_filename(const char *prefix, const char *name);
  extern void verify_non_filename(const char *prefix, const char *name);
  
@@@ -751,6 -750,8 +751,8 @@@ extern const char *git_author_info(int)
  extern const char *git_committer_info(int);
  extern const char *fmt_ident(const char *name, const char *email, const char *date_str, int);
  extern const char *fmt_name(const char *name, const char *email);
+ extern const char *git_editor(void);
+ extern const char *git_pager(void);
  
  struct checkout {
        const char *base_dir;
index 8ce1ec92c2b04e1271b3ee1a41a2ac60d2f8aad4,0c74e5c14ad15b3f90c2688b34637be5b70e3e0e..f813ffdaa1526aa68b4ed8e7d4d04b48e270496a
@@@ -731,17 -731,14 +731,17 @@@ sub parse_diff_header 
  
        my $head = { TEXT => [], DISPLAY => [], TYPE => 'header' };
        my $mode = { TEXT => [], DISPLAY => [], TYPE => 'mode' };
 +      my $deletion = { TEXT => [], DISPLAY => [], TYPE => 'deletion' };
  
        for (my $i = 0; $i < @{$src->{TEXT}}; $i++) {
 -              my $dest = $src->{TEXT}->[$i] =~ /^(old|new) mode (\d+)$/ ?
 -                      $mode : $head;
 +              my $dest =
 +                 $src->{TEXT}->[$i] =~ /^(old|new) mode (\d+)$/ ? $mode :
 +                 $src->{TEXT}->[$i] =~ /^deleted file/ ? $deletion :
 +                 $head;
                push @{$dest->{TEXT}}, $src->{TEXT}->[$i];
                push @{$dest->{DISPLAY}}, $src->{DISPLAY}->[$i];
        }
 -      return ($head, $mode);
 +      return ($head, $mode, $deletion);
  }
  
  sub hunk_splittable {
@@@ -990,8 -987,7 +990,7 @@@ sub edit_hunk_manually 
  EOF
        close $fh;
  
-       my $editor = $ENV{GIT_EDITOR} || $repo->config("core.editor")
-               || $ENV{VISUAL} || $ENV{EDITOR} || "vi";
+       chomp(my $editor = run_cmd_pipe(qw(git var GIT_EDITOR)));
        system('sh', '-c', $editor.' "$@"', $editor, $hunkfile);
  
        if ($? != 0) {
@@@ -1209,7 -1205,7 +1208,7 @@@ sub patch_update_file 
        my ($ix, $num);
        my $path = shift;
        my ($head, @hunk) = parse_diff($path);
 -      ($head, my $mode) = parse_diff_header($head);
 +      ($head, my $mode, my $deletion) = parse_diff_header($head);
        for (@{$head->{DISPLAY}}) {
                print;
        }
        if (@{$mode->{TEXT}}) {
                unshift @hunk, $mode;
        }
 +      if (@{$deletion->{TEXT}} && !@hunk) {
 +              @hunk = ($deletion);
 +      }
  
        $num = scalar @hunk;
        $ix = 0;
                        print;
                }
                print colored $prompt_color, $patch_mode_flavour{VERB},
 -                ($hunk[$ix]{TYPE} eq 'mode' ? ' mode change' : ' this hunk'),
 +                ($hunk[$ix]{TYPE} eq 'mode' ? ' mode change' :
 +                 $hunk[$ix]{TYPE} eq 'deletion' ? ' deletion' :
 +                 ' this hunk'),
                  $patch_mode_flavour{TARGET},
                  " [y,n,q,a,d,/$other,?]? ";
                my $line = prompt_single_character;
diff --combined git-svn.perl
index ab0a8dd0990ac030db046efdcdae74978a2d8c46,c4ca5487f3b485bb31a692a97c38156239f4bc9c..2746895ae620a37c4b84419caf221db8f476e197
@@@ -168,9 -168,6 +168,9 @@@ my %cmd = 
                             'Create a .gitignore per svn:ignore',
                             { 'revision|r=i' => \$_revision
                             } ],
 +      'mkdirs' => [ \&cmd_mkdirs ,
 +                    "recreate empty directories after a checkout",
 +                    { 'revision|r=i' => \$_revision } ],
          'propget' => [ \&cmd_propget,
                       'Print the value of a property on a file or directory',
                       { 'revision|r=i' => \$_revision } ],
@@@ -277,7 -274,7 +277,7 @@@ unless ($cmd && $cmd =~ /(?:clone|init|
  
  my %opts = %{$cmd{$cmd}->[2]} if (defined $cmd);
  
 -read_repo_config(\%opts);
 +read_git_config(\%opts);
  if ($cmd && ($cmd eq 'log' || $cmd eq 'blame')) {
        Getopt::Long::Configure('pass_through');
  }
@@@ -772,7 -769,6 +772,7 @@@ sub cmd_rebase 
                $_fetch_all ? $gs->fetch_all : $gs->fetch;
        }
        command_noisy(rebase_cmd(), $gs->refname);
 +      $gs->mkemptydirs;
  }
  
  sub cmd_show_ignore {
@@@ -834,12 -830,6 +834,12 @@@ sub cmd_create_ignore 
        });
  }
  
 +sub cmd_mkdirs {
 +      my ($url, $rev, $uuid, $gs) = working_head_info('HEAD');
 +      $gs ||= Git::SVN->new;
 +      $gs->mkemptydirs($_revision);
 +}
 +
  sub canonicalize_path {
        my ($path) = @_;
        my $dot_slash_added = 0;
@@@ -1206,7 -1196,6 +1206,7 @@@ sub post_fetch_checkout 
        command_noisy(qw/read-tree -m -u -v HEAD HEAD/);
        print STDERR "Checked out HEAD:\n  ",
                     $gs->full_url, " r", $gs->last_rev, "\n";
 +      $gs->mkemptydirs($gs->last_rev);
  }
  
  sub complete_svn_url {
@@@ -1332,9 -1321,8 +1332,8 @@@ sub get_commit_entry 
        close $log_fh or croak $!;
  
        if ($_edit || ($type eq 'tree')) {
-               my $editor = $ENV{VISUAL} || $ENV{EDITOR} || 'vi';
-               # TODO: strip out spaces, comments, like git-commit.sh
-               system($editor, $commit_editmsg);
+               chomp(my $editor = command_oneline(qw(var GIT_EDITOR)));
+               system('sh', '-c', $editor.' "$@"', $editor, $commit_editmsg);
        }
        rename $commit_editmsg, $commit_msg or croak $!;
        {
@@@ -1401,7 -1389,8 +1400,7 @@@ sub load_authors 
  }
  
  # convert GetOpt::Long specs for use by git-config
 -sub read_repo_config {
 -      return unless -d $ENV{GIT_DIR};
 +sub read_git_config {
        my $opts = shift;
        my @config_only;
        foreach my $o (keys %$opts) {
@@@ -2735,34 -2724,6 +2734,34 @@@ sub do_fetch 
        $self->make_log_entry($rev, \@parents, $ed);
  }
  
 +sub mkemptydirs {
 +      my ($self, $r) = @_;
 +      my %empty_dirs = ();
 +
 +      open my $fh, '<', "$self->{dir}/unhandled.log" or return;
 +      binmode $fh or croak "binmode: $!";
 +      while (<$fh>) {
 +              if (defined $r && /^r(\d+)$/) {
 +                      last if $1 > $r;
 +              } elsif (/^  \+empty_dir: (.+)$/) {
 +                      $empty_dirs{$1} = 1;
 +              } elsif (/^  \-empty_dir: (.+)$/) {
 +                      delete $empty_dirs{$1};
 +              }
 +      }
 +      close $fh;
 +      foreach my $d (sort keys %empty_dirs) {
 +              $d = uri_decode($d);
 +              next if -d $d;
 +              if (-e _) {
 +                      warn "$d exists but is not a directory\n";
 +              } else {
 +                      print "creating empty directory: $d\n";
 +                      mkpath([$d]);
 +              }
 +      }
 +}
 +
  sub get_untracked {
        my ($self, $ed) = @_;
        my @out;
@@@ -2988,11 -2949,8 +2987,11 @@@ sub find_extra_svn_parents 
                        my $bottom_commit =
                                $gs->rev_map_get($bottom, $self->ra_uuid) ||
                                $gs->rev_map_get($bottom+1, $self->ra_uuid);
 -                      my $top_commit =
 -                              $gs->rev_map_get($top, $self->ra_uuid);
 +                      my $top_commit;
 +                      for (; !$top_commit && $top >= $bottom; --$top) {
 +                              $top_commit =
 +                                      $gs->rev_map_get($top, $self->ra_uuid);
 +                      }
  
                        unless ($top_commit and $bottom_commit) {
                                warn "W:unknown path/rev in svn:mergeinfo "
@@@ -3595,12 -3553,6 +3594,12 @@@ sub uri_encode 
        $f
  }
  
 +sub uri_decode {
 +      my ($f) = @_;
 +      $f =~ s#%([0-9a-fA-F]{2})#chr(hex($1))#eg;
 +      $f
 +}
 +
  sub remove_username {
        $_[0] =~ s{^([^:]*://)[^@]+@}{$1};
  }
@@@ -5219,10 -5171,8 +5218,8 @@@ sub git_svn_log_cmd 
  
  # adapted from pager.c
  sub config_pager {
-       $pager ||= $ENV{GIT_PAGER} || $ENV{PAGER};
-       if (!defined $pager) {
-               $pager = 'less';
-       } elsif (length $pager == 0 || $pager eq 'cat') {
+       chomp(my $pager = command_oneline(qw(var GIT_PAGER)));
+       if ($pager eq 'cat') {
                $pager = undef;
        }
        $ENV{GIT_PAGER_IN_USE} = defined($pager);