Merge branch 'bw/grep-recurse-submodules'
authorJunio C Hamano <gitster@pobox.com>
Wed, 18 Jan 2017 23:12:11 +0000 (15:12 -0800)
committerJunio C Hamano <gitster@pobox.com>
Wed, 18 Jan 2017 23:12:11 +0000 (15:12 -0800)
"git grep" has been taught to optionally recurse into submodules.

* bw/grep-recurse-submodules:
grep: search history of moved submodules
grep: enable recurse-submodules to work on <tree> objects
grep: optionally recurse into submodules
grep: add submodules as a grep source type
submodules: load gitmodules file from commit sha1
submodules: add helper to determine if a submodule is initialized
submodules: add helper to determine if a submodule is populated
real_path: canonicalize directory separators in root parts
real_path: have callers use real_pathdup and strbuf_realpath
real_path: create real_pathdup
real_path: convert real_path_internal to strbuf_realpath
real_path: resolve symlinks by hand

1  2 
cache.h
config.c
environment.c
git.c
sha1_file.c
submodule-config.c
submodule-config.h
submodule.c
submodule.h
transport.c
worktree.c
diff --cc cache.h
Simple merge
diff --cc config.c
Simple merge
diff --cc environment.c
Simple merge
diff --cc git.c
Simple merge
diff --cc sha1_file.c
Simple merge
index ec13ab5a3dd82ac90c1c83d9e07dc8c045a992d2,8b9a2ef2888c3f12563b9392b4254905211e5aa5..4bf50f398a5bd705531e32f9329c0e3b7e630506
@@@ -379,9 -379,9 +379,9 @@@ static int parse_config(const char *var
        return ret;
  }
  
- static int gitmodule_sha1_from_commit(const unsigned char *treeish_name,
 -int gitmodule_sha1_from_commit(const unsigned char *commit_sha1,
 -                             unsigned char *gitmodules_sha1,
 -                             struct strbuf *rev)
++int gitmodule_sha1_from_commit(const unsigned char *treeish_name,
 +                                    unsigned char *gitmodules_sha1,
 +                                    struct strbuf *rev)
  {
        int ret = 0;
  
index 99df8e593cc7c274f88a73dfdd6524b7f661692c,78584ba6a715f38ebe5c30b7617c84afbc657fa0..70f19363fd8bf5b7f42e974dacdc3ed2cd58a96a
@@@ -25,10 -25,13 +25,13 @@@ struct submodule 
  int parse_fetch_recurse_submodules_arg(const char *opt, const char *arg);
  int parse_push_recurse_submodules_arg(const char *opt, const char *arg);
  int parse_submodule_config_option(const char *var, const char *value);
 -const struct submodule *submodule_from_name(const unsigned char *commit_sha1,
 +const struct submodule *submodule_from_name(const unsigned char *commit_or_tree,
                const char *name);
 -const struct submodule *submodule_from_path(const unsigned char *commit_sha1,
 +const struct submodule *submodule_from_path(const unsigned char *commit_or_tree,
                const char *path);
+ extern int gitmodule_sha1_from_commit(const unsigned char *commit_sha1,
+                                     unsigned char *gitmodules_sha1,
+                                     struct strbuf *rev);
  void submodule_free(void);
  
  #endif /* SUBMODULE_CONFIG_H */
diff --cc submodule.c
index 73521cdbb29abf7e3b1d9eb7293d16e94ec8ccce,260090898acf4701a96c51d13cf4834d107f5c55..f8fee3dfddd27b569b3b505877b569d30dcd656d
@@@ -1312,105 -1311,3 +1362,105 @@@ void prepare_submodule_repo_env(struct 
        }
        argv_array_push(out, "GIT_DIR=.git");
  }
-       real_old_git_dir = xstrdup(real_path(old_git_dir));
 +
 +/*
 + * Embeds a single submodules git directory into the superprojects git dir,
 + * non recursively.
 + */
 +static void relocate_single_git_dir_into_superproject(const char *prefix,
 +                                                    const char *path)
 +{
 +      char *old_git_dir = NULL, *real_old_git_dir = NULL, *real_new_git_dir = NULL;
 +      const char *new_git_dir;
 +      const struct submodule *sub;
 +
 +      if (submodule_uses_worktrees(path))
 +              die(_("relocate_gitdir for submodule '%s' with "
 +                    "more than one worktree not supported"), path);
 +
 +      old_git_dir = xstrfmt("%s/.git", path);
 +      if (read_gitfile(old_git_dir))
 +              /* If it is an actual gitfile, it doesn't need migration. */
 +              return;
 +
-       real_new_git_dir = xstrdup(real_path(new_git_dir));
++      real_old_git_dir = real_pathdup(old_git_dir);
 +
 +      sub = submodule_from_path(null_sha1, path);
 +      if (!sub)
 +              die(_("could not lookup name for submodule '%s'"), path);
 +
 +      new_git_dir = git_path("modules/%s", sub->name);
 +      if (safe_create_leading_directories_const(new_git_dir) < 0)
 +              die(_("could not create directory '%s'"), new_git_dir);
-       real_sub_git_dir = xstrdup(real_path(sub_git_dir));
-       real_common_git_dir = xstrdup(real_path(get_git_common_dir()));
++      real_new_git_dir = real_pathdup(new_git_dir);
 +
 +      if (!prefix)
 +              prefix = get_super_prefix();
 +
 +      fprintf(stderr, _("Migrating git directory of '%s%s' from\n'%s' to\n'%s'\n"),
 +              prefix ? prefix : "", path,
 +              real_old_git_dir, real_new_git_dir);
 +
 +      relocate_gitdir(path, real_old_git_dir, real_new_git_dir);
 +
 +      free(old_git_dir);
 +      free(real_old_git_dir);
 +      free(real_new_git_dir);
 +}
 +
 +/*
 + * Migrate the git directory of the submodule given by path from
 + * having its git directory within the working tree to the git dir nested
 + * in its superprojects git dir under modules/.
 + */
 +void absorb_git_dir_into_superproject(const char *prefix,
 +                                    const char *path,
 +                                    unsigned flags)
 +{
 +      const char *sub_git_dir, *v;
 +      char *real_sub_git_dir = NULL, *real_common_git_dir = NULL;
 +      struct strbuf gitdir = STRBUF_INIT;
 +
 +      strbuf_addf(&gitdir, "%s/.git", path);
 +      sub_git_dir = resolve_gitdir(gitdir.buf);
 +
 +      /* Not populated? */
 +      if (!sub_git_dir)
 +              goto out;
 +
 +      /* Is it already absorbed into the superprojects git dir? */
++      real_sub_git_dir = real_pathdup(sub_git_dir);
++      real_common_git_dir = real_pathdup(get_git_common_dir());
 +      if (!skip_prefix(real_sub_git_dir, real_common_git_dir, &v))
 +              relocate_single_git_dir_into_superproject(prefix, path);
 +
 +      if (flags & ABSORB_GITDIR_RECURSE_SUBMODULES) {
 +              struct child_process cp = CHILD_PROCESS_INIT;
 +              struct strbuf sb = STRBUF_INIT;
 +
 +              if (flags & ~ABSORB_GITDIR_RECURSE_SUBMODULES)
 +                      die("BUG: we don't know how to pass the flags down?");
 +
 +              if (get_super_prefix())
 +                      strbuf_addstr(&sb, get_super_prefix());
 +              strbuf_addstr(&sb, path);
 +              strbuf_addch(&sb, '/');
 +
 +              cp.dir = path;
 +              cp.git_cmd = 1;
 +              cp.no_stdin = 1;
 +              argv_array_pushl(&cp.args, "--super-prefix", sb.buf,
 +                                         "submodule--helper",
 +                                         "absorb-git-dirs", NULL);
 +              prepare_submodule_repo_env(&cp.env_array);
 +              if (run_command(&cp))
 +                      die(_("could not recurse into submodule '%s'"), path);
 +
 +              strbuf_release(&sb);
 +      }
 +
 +out:
 +      strbuf_release(&gitdir);
 +      free(real_sub_git_dir);
 +      free(real_common_git_dir);
 +}
diff --cc submodule.h
Simple merge
diff --cc transport.c
Simple merge
diff --cc worktree.c
Simple merge