Merge branch 'jl/some-submodule-config-are-not-boolean' into maint
authorJunio C Hamano <gitster@pobox.com>
Wed, 18 Sep 2013 18:59:35 +0000 (11:59 -0700)
committerJunio C Hamano <gitster@pobox.com>
Wed, 18 Sep 2013 18:59:35 +0000 (11:59 -0700)
* jl/some-submodule-config-are-not-boolean:
avoid segfault on submodule.*.path set to an empty "true"

1  2 
submodule.c
t/t7400-submodule-basic.sh
diff --combined submodule.c
index 3f0a3f9419a3dead24cd8e850051f595d0b5974f,8f7515ed6644a22e6f860eac72b2897e636cdf3d..c0f93c208c11b2dad0d508fcb7adf14873484385
@@@ -134,6 -134,9 +134,9 @@@ int parse_submodule_config_option(cons
                return 0;
  
        if (!strcmp(key, "path")) {
+               if (!value)
+                       return config_error_nonbool(var);
                config = unsorted_string_list_lookup(&config_name_for_path, value);
                if (config)
                        free(config->util);
        } else if (!strcmp(key, "ignore")) {
                char *name_cstr;
  
+               if (!value)
+                       return config_error_nonbool(var);
                if (strcmp(value, "untracked") && strcmp(value, "dirty") &&
                    strcmp(value, "all") && strcmp(value, "none")) {
                        warning("Invalid parameter \"%s\" for config option \"submodule.%s.ignore\"", value, var);
@@@ -216,7 -222,6 +222,7 @@@ static int prepare_submodule_summary(st
  }
  
  static void print_submodule_summary(struct rev_info *rev, FILE *f,
 +              const char *line_prefix,
                const char *del, const char *add, const char *reset)
  {
        static const char format[] = "  %m %s";
        while ((commit = get_revision(rev))) {
                struct pretty_print_context ctx = {0};
                ctx.date_mode = rev->date_mode;
 +              ctx.output_encoding = get_log_output_encoding();
                strbuf_setlen(&sb, 0);
 +              strbuf_addstr(&sb, line_prefix);
                if (commit->object.flags & SYMMETRIC_LEFT) {
                        if (del)
                                strbuf_addstr(&sb, del);
@@@ -259,7 -262,6 +265,7 @@@ int parse_fetch_recurse_submodules_arg(
  }
  
  void show_submodule_summary(FILE *f, const char *path,
 +              const char *line_prefix,
                unsigned char one[20], unsigned char two[20],
                unsigned dirty_submodule, const char *meta,
                const char *del, const char *add, const char *reset)
                message = "(revision walker failed)";
  
        if (dirty_submodule & DIRTY_SUBMODULE_UNTRACKED)
 -              fprintf(f, "Submodule %s contains untracked content\n", path);
 +              fprintf(f, "%sSubmodule %s contains untracked content\n",
 +                      line_prefix, path);
        if (dirty_submodule & DIRTY_SUBMODULE_MODIFIED)
 -              fprintf(f, "Submodule %s contains modified content\n", path);
 +              fprintf(f, "%sSubmodule %s contains modified content\n",
 +                      line_prefix, path);
  
        if (!hashcmp(one, two)) {
                strbuf_release(&sb);
                return;
        }
  
 -      strbuf_addf(&sb, "%sSubmodule %s %s..", meta, path,
 +      strbuf_addf(&sb, "%s%sSubmodule %s %s..", line_prefix, meta, path,
                        find_unique_abbrev(one, DEFAULT_ABBREV));
        if (!fast_backward && !fast_forward)
                strbuf_addch(&sb, '.');
        fwrite(sb.buf, sb.len, 1, f);
  
        if (!message) /* only NULL if we succeeded in setting up the walk */
 -              print_submodule_summary(&rev, f, del, add, reset);
 +              print_submodule_summary(&rev, f, line_prefix, del, add, reset);
        if (left)
                clear_commit_marks(left, ~0);
        if (right)
@@@ -604,8 -604,9 +610,8 @@@ int fetch_populated_submodules(const st
        if (!work_tree)
                goto out;
  
 -      if (!the_index.initialized)
 -              if (read_cache() < 0)
 -                      die("index file corrupt");
 +      if (read_cache() < 0)
 +              die("index file corrupt");
  
        argv_array_push(&argv, "fetch");
        for (i = 0; i < options->argc; i++)
                struct strbuf submodule_path = STRBUF_INIT;
                struct strbuf submodule_git_dir = STRBUF_INIT;
                struct strbuf submodule_prefix = STRBUF_INIT;
 -              struct cache_entry *ce = active_cache[i];
 +              const struct cache_entry *ce = active_cache[i];
                const char *git_dir, *name, *default_argv;
  
                if (!S_ISGITLINK(ce->ce_mode))
@@@ -846,7 -847,7 +852,7 @@@ static int find_first_merges(struct obj
                struct commit *a, struct commit *b)
  {
        int i, j;
 -      struct object_array merges;
 +      struct object_array merges = OBJECT_ARRAY_INIT;
        struct commit *commit;
        int contains_another;
  
        struct rev_info revs;
        struct setup_revision_opt rev_opts;
  
 -      memset(&merges, 0, sizeof(merges));
        memset(result, 0, sizeof(struct object_array));
        memset(&rev_opts, 0, sizeof(rev_opts));
  
                }
  
                if (!contains_another)
 -                      add_object_array(merges.objects[i].item,
 -                                       merges.objects[i].name, result);
 +                      add_object_array(merges.objects[i].item, NULL, result);
        }
  
        free(merges.objects);
index 5ee97b003a879a0b6a558265e94c18582aa836c0,0edf74c68f6907aedc8c863d573138c31e7110f2..a39d07446508598dded68561a946e8385a7830c3
@@@ -18,6 -18,16 +18,16 @@@ test_expect_success 'setup - initial co
        git branch initial
  '
  
+ test_expect_success 'configuration parsing' '
+       test_when_finished "rm -f .gitmodules" &&
+       cat >.gitmodules <<-\EOF &&
+       [submodule "s"]
+               path
+               ignore
+       EOF
+       test_must_fail git status
+ '
  test_expect_success 'setup - repository in init subdirectory' '
        mkdir init &&
        (
@@@ -78,7 -88,7 +88,7 @@@ test_expect_success 'submodule add' 
        (
                cd addtest &&
                git submodule add -q "$submodurl" submod >actual &&
 -              test ! -s actual &&
 +              test_must_be_empty actual &&
                echo "gitdir: ../.git/modules/submod" >expect &&
                test_cmp expect submod/.git &&
                (
@@@ -212,32 -222,6 +222,32 @@@ test_expect_success 'submodule add wit
        test_cmp empty untracked
  '
  
 +test_expect_success 'submodule add in subdirectory' '
 +      echo "refs/heads/master" >expect &&
 +      >empty &&
 +
 +      mkdir addtest/sub &&
 +      (
 +              cd addtest/sub &&
 +              git submodule add "$submodurl" ../realsubmod3 &&
 +              git submodule init
 +      ) &&
 +
 +      rm -f heads head untracked &&
 +      inspect addtest/realsubmod3 ../.. &&
 +      test_cmp expect heads &&
 +      test_cmp expect head &&
 +      test_cmp empty untracked
 +'
 +
 +test_expect_success 'submodule add in subdirectory with relative path should fail' '
 +      (
 +              cd addtest/sub &&
 +              test_must_fail git submodule add ../../ submod3 2>../../output.err
 +      ) &&
 +      test_i18ngrep toplevel output.err
 +'
 +
  test_expect_success 'setup - add an example entry to .gitmodules' '
        GIT_CONFIG=.gitmodules \
        git config submodule.example.url git://example.com/init.git
@@@ -334,7 -318,7 +344,7 @@@ test_expect_success 'update should wor
  
        mkdir init &&
        git submodule update -q >update.out &&
 -      test ! -s update.out &&
 +      test_must_be_empty update.out &&
  
        inspect init &&
        test_cmp expect head-sha1
@@@ -345,26 -329,6 +355,26 @@@ test_expect_success 'status should be "
        grep "^ $rev1" list
  '
  
 +test_expect_success 'status "up-to-date" from subdirectory' '
 +      mkdir -p sub &&
 +      (
 +              cd sub &&
 +              git submodule status >../list
 +      ) &&
 +      grep "^ $rev1" list &&
 +      grep "\\.\\./init" list
 +'
 +
 +test_expect_success 'status "up-to-date" from subdirectory with path' '
 +      mkdir -p sub &&
 +      (
 +              cd sub &&
 +              git submodule status ../init >../list
 +      ) &&
 +      grep "^ $rev1" list &&
 +      grep "\\.\\./init" list
 +'
 +
  test_expect_success 'status should be "modified" after submodule commit' '
        (
                cd init &&
@@@ -445,25 -409,6 +455,25 @@@ test_expect_success 'update --init' 
        git rev-parse --resolve-git-dir init/.git
  '
  
 +test_expect_success 'update --init from subdirectory' '
 +      mv init init2 &&
 +      git config -f .gitmodules submodule.example.url "$(pwd)/init2" &&
 +      git config --remove-section submodule.example &&
 +      test_must_fail git config submodule.example.url &&
 +
 +      mkdir -p sub &&
 +      (
 +              cd sub &&
 +              git submodule update ../init >update.out &&
 +              cat update.out &&
 +              test_i18ngrep "not initialized" update.out &&
 +              test_must_fail git rev-parse --resolve-git-dir ../init/.git &&
 +
 +              git submodule update --init ../init
 +      ) &&
 +      git rev-parse --resolve-git-dir init/.git
 +'
 +
  test_expect_success 'do not add files from a submodule' '
  
        git reset --hard &&
@@@ -761,7 -706,7 +771,7 @@@ test_expect_success 'submodule add --na
                rm -rf repo &&
                git rm repo &&
                git submodule add -q --name repo_new "$submodurl/bare.git" repo >actual &&
 -              test ! -s actual &&
 +              test_must_be_empty actual &&
                echo "gitdir: ../.git/modules/submod" >expect &&
                test_cmp expect submod/.git &&
                (
@@@ -822,161 -767,4 +832,161 @@@ test_expect_success 'submodule add wit
        )
  '
  
 +test_expect_success 'set up a second submodule' '
 +      git submodule add ./init2 example2 &&
 +      git commit -m "submodule example2 added"
 +'
 +
 +test_expect_success 'submodule deinit should remove the whole submodule section from .git/config' '
 +      git config submodule.example.foo bar &&
 +      git config submodule.example2.frotz nitfol &&
 +      git submodule deinit init &&
 +      test -z "$(git config --get-regexp "submodule\.example\.")" &&
 +      test -n "$(git config --get-regexp "submodule\.example2\.")" &&
 +      test -f example2/.git &&
 +      rmdir init
 +'
 +
 +test_expect_success 'submodule deinit from subdirectory' '
 +      git submodule update --init &&
 +      git config submodule.example.foo bar &&
 +      mkdir -p sub &&
 +      (
 +              cd sub &&
 +              git submodule deinit ../init >../output
 +      ) &&
 +      grep "\\.\\./init" output &&
 +      test -z "$(git config --get-regexp "submodule\.example\.")" &&
 +      test -n "$(git config --get-regexp "submodule\.example2\.")" &&
 +      test -f example2/.git &&
 +      rmdir init
 +'
 +
 +test_expect_success 'submodule deinit . deinits all initialized submodules' '
 +      git submodule update --init &&
 +      git config submodule.example.foo bar &&
 +      git config submodule.example2.frotz nitfol &&
 +      test_must_fail git submodule deinit &&
 +      git submodule deinit . >actual &&
 +      test -z "$(git config --get-regexp "submodule\.example\.")" &&
 +      test -z "$(git config --get-regexp "submodule\.example2\.")" &&
 +      test_i18ngrep "Cleared directory .init" actual &&
 +      test_i18ngrep "Cleared directory .example2" actual &&
 +      rmdir init example2
 +'
 +
 +test_expect_success 'submodule deinit deinits a submodule when its work tree is missing or empty' '
 +      git submodule update --init &&
 +      rm -rf init example2/* example2/.git &&
 +      git submodule deinit init example2 >actual &&
 +      test -z "$(git config --get-regexp "submodule\.example\.")" &&
 +      test -z "$(git config --get-regexp "submodule\.example2\.")" &&
 +      test_i18ngrep ! "Cleared directory .init" actual &&
 +      test_i18ngrep "Cleared directory .example2" actual &&
 +      rmdir init
 +'
 +
 +test_expect_success 'submodule deinit fails when the submodule contains modifications unless forced' '
 +      git submodule update --init &&
 +      echo X >>init/s &&
 +      test_must_fail git submodule deinit init &&
 +      test -n "$(git config --get-regexp "submodule\.example\.")" &&
 +      test -f example2/.git &&
 +      git submodule deinit -f init >actual &&
 +      test -z "$(git config --get-regexp "submodule\.example\.")" &&
 +      test_i18ngrep "Cleared directory .init" actual &&
 +      rmdir init
 +'
 +
 +test_expect_success 'submodule deinit fails when the submodule contains untracked files unless forced' '
 +      git submodule update --init &&
 +      echo X >>init/untracked &&
 +      test_must_fail git submodule deinit init &&
 +      test -n "$(git config --get-regexp "submodule\.example\.")" &&
 +      test -f example2/.git &&
 +      git submodule deinit -f init >actual &&
 +      test -z "$(git config --get-regexp "submodule\.example\.")" &&
 +      test_i18ngrep "Cleared directory .init" actual &&
 +      rmdir init
 +'
 +
 +test_expect_success 'submodule deinit fails when the submodule HEAD does not match unless forced' '
 +      git submodule update --init &&
 +      (
 +              cd init &&
 +              git checkout HEAD^
 +      ) &&
 +      test_must_fail git submodule deinit init &&
 +      test -n "$(git config --get-regexp "submodule\.example\.")" &&
 +      test -f example2/.git &&
 +      git submodule deinit -f init >actual &&
 +      test -z "$(git config --get-regexp "submodule\.example\.")" &&
 +      test_i18ngrep "Cleared directory .init" actual &&
 +      rmdir init
 +'
 +
 +test_expect_success 'submodule deinit is silent when used on an uninitialized submodule' '
 +      git submodule update --init &&
 +      git submodule deinit init >actual &&
 +      test_i18ngrep "Submodule .example. (.*) unregistered for path .init" actual &&
 +      test_i18ngrep "Cleared directory .init" actual &&
 +      git submodule deinit init >actual &&
 +      test_i18ngrep ! "Submodule .example. (.*) unregistered for path .init" actual &&
 +      test_i18ngrep "Cleared directory .init" actual &&
 +      git submodule deinit . >actual &&
 +      test_i18ngrep ! "Submodule .example. (.*) unregistered for path .init" actual &&
 +      test_i18ngrep "Submodule .example2. (.*) unregistered for path .example2" actual &&
 +      test_i18ngrep "Cleared directory .init" actual &&
 +      git submodule deinit . >actual &&
 +      test_i18ngrep ! "Submodule .example. (.*) unregistered for path .init" actual &&
 +      test_i18ngrep ! "Submodule .example2. (.*) unregistered for path .example2" actual &&
 +      test_i18ngrep "Cleared directory .init" actual &&
 +      rmdir init example2
 +'
 +
 +test_expect_success 'submodule deinit fails when submodule has a .git directory even when forced' '
 +      git submodule update --init &&
 +      (
 +              cd init &&
 +              rm .git &&
 +              cp -R ../.git/modules/example .git &&
 +              GIT_WORK_TREE=. git config --unset core.worktree
 +      ) &&
 +      test_must_fail git submodule deinit init &&
 +      test_must_fail git submodule deinit -f init &&
 +      test -d init/.git &&
 +      test -n "$(git config --get-regexp "submodule\.example\.")"
 +'
 +
 +test_expect_success 'submodule with UTF-8 name' '
 +      svname=$(printf "\303\245 \303\244\303\266") &&
 +      mkdir "$svname" &&
 +      (
 +              cd "$svname" &&
 +              git init &&
 +              >sub &&
 +              git add sub &&
 +              git commit -m "init sub"
 +      ) &&
 +      test_config core.precomposeunicode true &&
 +      git submodule add ./"$svname" &&
 +      git submodule >&2 &&
 +      test -n "$(git submodule | grep "$svname")"
 +'
 +
 +test_expect_success 'submodule add clone shallow submodule' '
 +      mkdir super &&
 +      pwd=$(pwd)
 +      (
 +              cd super &&
 +              git init &&
 +              git submodule add --depth=1 file://"$pwd"/example2 submodule &&
 +              (
 +                      cd submodule &&
 +                      test 1 = $(git log --oneline | wc -l)
 +              )
 +      )
 +'
 +
 +
  test_done