Merge branch 'jk/maint-1.6.2-upload-archive' into jk/maint-upload-archive
authorJunio C Hamano <gitster@pobox.com>
Mon, 21 Nov 2011 23:04:11 +0000 (15:04 -0800)
committerJunio C Hamano <gitster@pobox.com>
Mon, 21 Nov 2011 23:04:11 +0000 (15:04 -0800)
* jk/maint-1.6.2-upload-archive:
archive: don't let remote clients get unreachable commits

Conflicts:
archive.c
archive.h
builtin-archive.c
builtin/upload-archive.c
t/t5000-tar-tree.sh

1  2 
archive.c
t/t5000-tar-tree.sh
diff --cc archive.c
index 3fd7f475f1d8ff5efe602a10f02ea3e1c3aa9edd,251d69e153b2b548a9c41953652479c818fd81aa..5f0a3fc6d2e5cbf6e098fc67e093707bf2915914
+++ b/archive.c
@@@ -397,49 -339,14 +407,49 @@@ int write_archive(int argc, const char 
        const struct archiver *ar = NULL;
        struct archiver_args args;
  
 -      argc = parse_archive_args(argc, argv, &ar, &args);
        if (setup_prefix && prefix == NULL)
 -              prefix = setup_git_directory();
 +              prefix = setup_git_directory_gently(&nongit);
 +
 +      git_config(git_default_config, NULL);
 +      init_tar_archiver();
 +      init_zip_archiver();
 +
 +      argc = parse_archive_args(argc, argv, &ar, &args, name_hint, remote);
 +      if (nongit) {
 +              /*
 +               * We know this will die() with an error, so we could just
 +               * die ourselves; but its error message will be more specific
 +               * than what we could write here.
 +               */
 +              setup_git_directory();
 +      }
  
-       parse_treeish_arg(argv, &args, prefix);
+       parse_treeish_arg(argv, &args, prefix, remote);
        parse_pathspec_arg(argv + 1, &args);
  
 -      git_config(git_default_config, NULL);
 +      return ar->write_archive(ar, &args);
 +}
  
 -      return ar->write_archive(&args);
 +static int match_extension(const char *filename, const char *ext)
 +{
 +      int prefixlen = strlen(filename) - strlen(ext);
 +
 +      /*
 +       * We need 1 character for the '.', and 1 character to ensure that the
 +       * prefix is non-empty (k.e., we don't match .tar.gz with no actual
 +       * filename).
 +       */
 +      if (prefixlen < 2 || filename[prefixlen-1] != '.')
 +              return 0;
 +      return !strcmp(filename + prefixlen, ext);
 +}
 +
 +const char *archive_format_from_filename(const char *filename)
 +{
 +      int i;
 +
 +      for (i = 0; i < nr_archivers; i++)
 +              if (match_extension(filename, archivers[i]->name))
 +                      return archivers[i]->name;
 +      return NULL;
  }
index d9068981f8475c37d30e584bc6b795075a2f3063,1a2ee105a464ad007727cb2e4bd42de686c0d005..c05c676ca206c88bf77941d76b0bb717b374c9f8
@@@ -242,114 -213,12 +242,122 @@@ test_expect_success 
      'git archive --list outside of a git repo' \
      'GIT_DIR=some/non-existing/directory git archive --list'
  
+ test_expect_success 'clients cannot access unreachable commits' '
+       test_commit unreachable &&
+       sha1=`git rev-parse HEAD` &&
+       git reset --hard HEAD^ &&
+       git archive $sha1 >remote.tar &&
+       test_must_fail git archive --remote=. $sha1 >remote.tar
+ '
 +test_expect_success 'git-archive --prefix=olde-' '
 +      git archive --prefix=olde- >h.tar HEAD &&
 +      (
 +              mkdir h &&
 +              cd h &&
 +              "$TAR" xf - <../h.tar
 +      ) &&
 +      test -d h/olde-a &&
 +      test -d h/olde-a/bin &&
 +      test -f h/olde-a/bin/sh
 +'
 +
 +test_expect_success 'setup tar filters' '
 +      git config tar.tar.foo.command "tr ab ba" &&
 +      git config tar.bar.command "tr ab ba" &&
 +      git config tar.bar.remote true
 +'
 +
 +test_expect_success 'archive --list mentions user filter' '
 +      git archive --list >output &&
 +      grep "^tar\.foo\$" output &&
 +      grep "^bar\$" output
 +'
 +
 +test_expect_success NOT_MINGW 'archive --list shows only enabled remote filters' '
 +      git archive --list --remote=. >output &&
 +      ! grep "^tar\.foo\$" output &&
 +      grep "^bar\$" output
 +'
 +
 +test_expect_success 'invoke tar filter by format' '
 +      git archive --format=tar.foo HEAD >config.tar.foo &&
 +      tr ab ba <config.tar.foo >config.tar &&
 +      test_cmp b.tar config.tar &&
 +      git archive --format=bar HEAD >config.bar &&
 +      tr ab ba <config.bar >config.tar &&
 +      test_cmp b.tar config.tar
 +'
 +
 +test_expect_success 'invoke tar filter by extension' '
 +      git archive -o config-implicit.tar.foo HEAD &&
 +      test_cmp config.tar.foo config-implicit.tar.foo &&
 +      git archive -o config-implicit.bar HEAD &&
 +      test_cmp config.tar.foo config-implicit.bar
 +'
 +
 +test_expect_success 'default output format remains tar' '
 +      git archive -o config-implicit.baz HEAD &&
 +      test_cmp b.tar config-implicit.baz
 +'
 +
 +test_expect_success 'extension matching requires dot' '
 +      git archive -o config-implicittar.foo HEAD &&
 +      test_cmp b.tar config-implicittar.foo
 +'
 +
 +test_expect_success NOT_MINGW 'only enabled filters are available remotely' '
 +      test_must_fail git archive --remote=. --format=tar.foo HEAD \
 +              >remote.tar.foo &&
 +      git archive --remote=. --format=bar >remote.bar HEAD &&
 +      test_cmp remote.bar config.bar
 +'
 +
 +if $GZIP --version >/dev/null 2>&1; then
 +      test_set_prereq GZIP
 +else
 +      say "Skipping some tar.gz tests because gzip not found"
 +fi
 +
 +test_expect_success GZIP 'git archive --format=tgz' '
 +      git archive --format=tgz HEAD >j.tgz
 +'
 +
 +test_expect_success GZIP 'git archive --format=tar.gz' '
 +      git archive --format=tar.gz HEAD >j1.tar.gz &&
 +      test_cmp j.tgz j1.tar.gz
 +'
 +
 +test_expect_success GZIP 'infer tgz from .tgz filename' '
 +      git archive --output=j2.tgz HEAD &&
 +      test_cmp j.tgz j2.tgz
 +'
 +
 +test_expect_success GZIP 'infer tgz from .tar.gz filename' '
 +      git archive --output=j3.tar.gz HEAD &&
 +      test_cmp j.tgz j3.tar.gz
 +'
 +
 +if $GUNZIP --version >/dev/null 2>&1; then
 +      test_set_prereq GUNZIP
 +else
 +      say "Skipping some tar.gz tests because gunzip was not found"
 +fi
 +
 +test_expect_success GZIP,GUNZIP 'extract tgz file' '
 +      $GUNZIP -c <j.tgz >j.tar &&
 +      test_cmp b.tar j.tar
 +'
 +
 +test_expect_success GZIP,NOT_MINGW 'remote tar.gz is allowed by default' '
 +      git archive --remote=. --format=tar.gz HEAD >remote.tar.gz &&
 +      test_cmp j.tgz remote.tar.gz
 +'
 +
 +test_expect_success GZIP,NOT_MINGW 'remote tar.gz can be disabled' '
 +      git config tar.tar.gz.remote false &&
 +      test_must_fail git archive --remote=. --format=tar.gz HEAD \
 +              >remote.tar.gz
 +'
 +
  test_done