git/submodule.c

#define USE_THE_REPOSITORY_VARIABLE

#include "git-compat-util.h"
#include "abspath.h"
#include "repository.h"
#include "config.h"
#include "submodule-config.h"
#include "submodule.h"
#include "dir.h"
#include "diff.h"
#include "commit.h"
#include "environment.h"
#include "gettext.h"
#include "hex.h"
#include "revision.h"
#include "run-command.h"
#include "diffcore.h"
#include "refs.h"
#include "string-list.h"
#include "oid-array.h"
#include "strvec.h"
#include "thread-utils.h"
#include "path.h"
#include "remote.h"
#include "worktree.h"
#include "parse-options.h"
#include "object-file.h"
#include "object-name.h"
#include "object-store-ll.h"
#include "commit-reach.h"
#include "read-cache-ll.h"
#include "setup.h"
#include "trace2.h"

static int config_update_recurse_submodules =;
static int initialized_fetch_ref_tips;
static struct oid_array ref_tips_before_fetch;
static struct oid_array ref_tips_after_fetch;

/*
 * Check if the .gitmodules file is unmerged. Parsing of the .gitmodules file
 * will be disabled because we can't guess what might be configured in
 * .gitmodules unless the user resolves the conflict.
 */
int is_gitmodules_unmerged(struct index_state *istate)
{}

/*
 * Check if the .gitmodules file is safe to write.
 *
 * Writing to the .gitmodules file requires that the file exists in the
 * working tree or, if it doesn't, that a brand new .gitmodules file is going
 * to be created (i.e. it's neither in the index nor in the current branch).
 *
 * It is not safe to write to .gitmodules if it's not in the working tree but
 * it is in the index or in the current branch, because writing new values
 * (and staging them) would blindly overwrite ALL the old content.
 */
int is_writing_gitmodules_ok(void)
{}

/*
 * Check if the .gitmodules file has unstaged modifications.  This must be
 * checked before allowing modifications to the .gitmodules file with the
 * intention to stage them later, because when continuing we would stage the
 * modifications the user didn't stage herself too. That might change in a
 * future version when we learn to stage the changes we do ourselves without
 * staging any previous modifications.
 */
int is_staging_gitmodules_ok(struct index_state *istate)
{}

static int for_each_remote_ref_submodule(const char *submodule,
					 each_ref_fn fn, void *cb_data)
{}

/*
 * Try to update the "path" entry in the "submodule.<name>" section of the
 * .gitmodules file. Return 0 only if a .gitmodules file was found, a section
 * with the correct path=<oldpath> setting was found and we could update it.
 */
int update_path_in_gitmodules(const char *oldpath, const char *newpath)
{}

/*
 * Try to remove the "submodule.<name>" section from .gitmodules where the given
 * path is configured. Return 0 only if a .gitmodules file was found, a section
 * with the correct path=<path> setting was found and we could remove it.
 */
int remove_path_from_gitmodules(const char *path)
{}

void stage_updated_gitmodules(struct index_state *istate)
{}

static struct string_list added_submodule_odb_paths =;

void add_submodule_odb_by_path(const char *path)
{}

int register_all_submodule_odb_as_alternates(void)
{}

void set_diffopt_flags_from_submodule_config(struct diff_options *diffopt,
					     const char *path)
{}

/* Cheap function that only determines if we're interested in submodules at all */
int git_default_submodule_config(const char *var, const char *value,
				 void *cb UNUSED)
{}

int option_parse_recurse_submodules_worktree_updater(const struct option *opt,
						     const char *arg, int unset)
{}

/*
 * Determine if a submodule has been initialized at a given 'path'
 */
/*
 * NEEDSWORK: Emit a warning if submodule.active exists, but is valueless,
 * ie, the config looks like: "[submodule] active\n".
 * Since that is an invalid pathspec, we should inform the user.
 */
int is_tree_submodule_active(struct repository *repo,
			     const struct object_id *treeish_name,
			     const char *path)
{}

int is_submodule_active(struct repository *repo, const char *path)
{}

int is_submodule_populated_gently(const char *path, int *return_error_code)
{}

/*
 * Dies if the provided 'prefix' corresponds to an unpopulated submodule
 */
void die_in_unpopulated_submodule(struct index_state *istate,
				  const char *prefix)
{}

/*
 * Dies if any paths in the provided pathspec descends into a submodule
 */
void die_path_inside_submodule(struct index_state *istate,
			       const struct pathspec *ps)
{}

enum submodule_update_type parse_submodule_update_type(const char *value)
{}

int parse_submodule_update_strategy(const char *value,
		struct submodule_update_strategy *dst)
{}

void submodule_update_strategy_release(struct submodule_update_strategy *strategy)
{}

const char *submodule_update_type_to_string(enum submodule_update_type type)
{}

void handle_ignore_submodules_arg(struct diff_options *diffopt,
				  const char *arg)
{}

static int prepare_submodule_diff_summary(struct repository *r, struct rev_info *rev,
					  const char *path,
					  struct commit *left, struct commit *right,
					  struct commit_list *merge_bases)
{}

static void print_submodule_diff_summary(struct repository *r, struct rev_info *rev, struct diff_options *o)
{}

void prepare_submodule_repo_env(struct strvec *out)
{}

static void prepare_submodule_repo_env_in_gitdir(struct strvec *out)
{}

/*
 * Initialize a repository struct for a submodule based on the provided 'path'.
 *
 * Returns the repository struct on success,
 * NULL when the submodule is not present.
 */
static struct repository *open_submodule(const char *path)
{}

/*
 * Helper function to display the submodule header line prior to the full
 * summary output.
 *
 * If it can locate the submodule git directory it will create a repository
 * handle for the submodule and lookup both the left and right commits and
 * put them into the left and right pointers.
 */
static void show_submodule_header(struct diff_options *o,
		const char *path,
		struct object_id *one, struct object_id *two,
		unsigned dirty_submodule,
		struct repository *sub,
		struct commit **left, struct commit **right,
		struct commit_list **merge_bases)
{}

void show_submodule_diff_summary(struct diff_options *o, const char *path,
		struct object_id *one, struct object_id *two,
		unsigned dirty_submodule)
{}

void show_submodule_inline_diff(struct diff_options *o, const char *path,
		struct object_id *one, struct object_id *two,
		unsigned dirty_submodule)
{}

int should_update_submodules(void)
{}

const struct submodule *submodule_from_ce(const struct cache_entry *ce)
{}


struct collect_changed_submodules_cb_data {};

/*
 * this would normally be two functions: default_name_from_path() and
 * path_from_default_name(). Since the default name is the same as
 * the submodule path we can get away with just one function which only
 * checks whether there is a submodule in the working directory at that
 * location.
 */
static const char *default_name_or_path(const char *path_or_name)
{}

/*
 * Holds relevant information for a changed submodule. Used as the .util
 * member of the changed submodule name string_list_item.
 *
 * (super_oid, path) allows the submodule config to be read from _some_
 * .gitmodules file. We store this information the first time we find a
 * superproject commit that points to the submodule, but this is
 * arbitrary - we can choose any (super_oid, path) that matches the
 * submodule's name.
 *
 * NEEDSWORK: Storing an arbitrary commit is undesirable because we can't
 * guarantee that we're reading the commit that the user would expect. A better
 * scheme would be to just fetch a submodule by its name. This requires two
 * steps:
 * - Create a function that behaves like repo_submodule_init(), but accepts a
 *   submodule name instead of treeish_name and path. This should be easy
 *   because repo_submodule_init() internally uses the submodule's name.
 *
 * - Replace most instances of 'struct submodule' (which is the .gitmodules
 *   config) with just the submodule name. This is OK because we expect
 *   submodule settings to be stored in .git/config (via "git submodule init"),
 *   not .gitmodules. This also lets us delete get_non_gitmodules_submodule(),
 *   which constructs a bogus 'struct submodule' for the sake of giving a
 *   placeholder name to a gitlink.
 */
struct changed_submodule_data {};

static void changed_submodule_data_clear(struct changed_submodule_data *cs_data)
{}

static void collect_changed_submodules_cb(struct diff_queue_struct *q,
					  struct diff_options *options UNUSED,
					  void *data)
{}

/*
 * Collect the paths of submodules in 'changed' which have changed based on
 * the revisions as specified in 'argv'.  Each entry in 'changed' will also
 * have a corresponding 'struct oid_array' (in the 'util' field) which lists
 * what the submodule pointers were updated to during the change.
 */
static void collect_changed_submodules(struct repository *r,
				       struct string_list *changed,
				       struct strvec *argv)
{}

static void free_submodules_data(struct string_list *submodules)
{}

static int has_remote(const char *refname UNUSED,
		      const char *referent UNUSED,
		      const struct object_id *oid UNUSED,
		      int flags UNUSED, void *cb_data UNUSED)
{}

static int append_oid_to_argv(const struct object_id *oid, void *data)
{}

struct has_commit_data {};

static int check_has_commit(const struct object_id *oid, void *data)
{}

static int submodule_has_commits(struct repository *r,
				 const char *path,
				 const struct object_id *super_oid,
				 struct oid_array *commits)
{}

static int submodule_needs_pushing(struct repository *r,
				   const char *path,
				   struct oid_array *commits)
{}

int find_unpushed_submodules(struct repository *r,
			     struct oid_array *commits,
			     const char *remotes_name,
			     struct string_list *needs_pushing)
{}

static int push_submodule(const char *path,
			  const struct remote *remote,
			  const struct refspec *rs,
			  const struct string_list *push_options,
			  int dry_run)
{}

/*
 * Perform a check in the submodule to see if the remote and refspec work.
 * Die if the submodule can't be pushed.
 */
static void submodule_push_check(const char *path, const char *head,
				 const struct remote *remote,
				 const struct refspec *rs)
{}

int push_unpushed_submodules(struct repository *r,
			     struct oid_array *commits,
			     const struct remote *remote,
			     const struct refspec *rs,
			     const struct string_list *push_options,
			     int dry_run)
{}

static int append_oid_to_array(const char *ref UNUSED,
			       const char *referent UNUSED,
			       const struct object_id *oid,
			       int flags UNUSED, void *data)
{}

void check_for_new_submodule_commits(struct object_id *oid)
{}

/*
 * Returns 1 if there is at least one submodule gitdir in
 * $GIT_DIR/modules and 0 otherwise. This follows
 * submodule_name_to_gitdir(), which looks for submodules in
 * $GIT_DIR/modules, not $GIT_COMMON_DIR.
 *
 * A submodule can be moved to $GIT_DIR/modules manually by running "git
 * submodule absorbgitdirs", or it may be initialized there by "git
 * submodule update".
 */
static int repo_has_absorbed_submodules(struct repository *r)
{}

static void calculate_changed_submodule_paths(struct repository *r,
		struct string_list *changed_submodule_names)
{}

int submodule_touches_in_range(struct repository *r,
			       struct object_id *excl_oid,
			       struct object_id *incl_oid)
{}

struct submodule_parallel_fetch {};
#define SPF_INIT

static int get_fetch_recurse_config(const struct submodule *submodule,
				    struct submodule_parallel_fetch *spf)
{}

/*
 * Fetch in progress (if callback data) or
 * pending (if in oid_fetch_tasks in struct submodule_parallel_fetch)
 */
struct fetch_task {};

/**
 * When a submodule is not defined in .gitmodules, we cannot access it
 * via the regular submodule-config. Create a fake submodule, which we can
 * work on.
 */
static const struct submodule *get_non_gitmodules_submodule(const char *path)
{}

static void fetch_task_free(struct fetch_task *p)
{}

static struct repository *get_submodule_repo_for(struct repository *r,
						 const char *path,
						 const struct object_id *treeish_name)
{}

static struct fetch_task *fetch_task_create(struct submodule_parallel_fetch *spf,
					    const char *path,
					    const struct object_id *treeish_name)
{}

static struct fetch_task *
get_fetch_task_from_index(struct submodule_parallel_fetch *spf,
			  struct strbuf *err)
{}

static struct fetch_task *
get_fetch_task_from_changed(struct submodule_parallel_fetch *spf,
			    struct strbuf *err)
{}

static int get_next_submodule(struct child_process *cp, struct strbuf *err,
			      void *data, void **task_cb)
{}

static int fetch_start_failure(struct strbuf *err UNUSED,
			       void *cb, void *task_cb)
{}

static int commit_missing_in_sub(const struct object_id *oid, void *data)
{}

static int fetch_finish(int retvalue, struct strbuf *err UNUSED,
			void *cb, void *task_cb)
{}

int fetch_submodules(struct repository *r,
		     const struct strvec *options,
		     const char *prefix, int command_line_option,
		     int default_option,
		     int quiet, int max_parallel_jobs)
{}

unsigned is_submodule_modified(const char *path, int ignore_untracked)
{}

int submodule_uses_gitfile(const char *path)
{}

/*
 * Check if it is a bad idea to remove a submodule, i.e. if we'd lose data
 * when doing so.
 *
 * Return 1 if we'd lose data, return 0 if the removal is fine,
 * and negative values for errors.
 */
int bad_to_remove_submodule(const char *path, unsigned flags)
{}

void submodule_unset_core_worktree(const struct submodule *sub)
{}

static int submodule_has_dirty_index(const struct submodule *sub)
{}

static void submodule_reset_index(const char *path, const char *super_prefix)
{}

/**
 * Moves a submodule at a given path from a given head to another new head.
 * For edge cases (a submodule coming into existence or removing a submodule)
 * pass NULL for old or new respectively.
 */
int submodule_move_head(const char *path, const char *super_prefix,
			const char *old_head, const char *new_head,
			unsigned flags)
{}

int validate_submodule_git_dir(char *git_dir, const char *submodule_name)
{}

int validate_submodule_path(const char *path)
{}


/*
 * Embeds a single submodules git directory into the superprojects git dir,
 * non recursively.
 */
static void relocate_single_git_dir_into_superproject(const char *path,
						      const char *super_prefix)
{}

static void absorb_git_dir_into_superproject_recurse(const char *path,
						     const char *super_prefix)
{}

/*
 * 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 *path,
				      const char *super_prefix)
{}

int get_superproject_working_tree(struct strbuf *buf)
{}

/*
 * Put the gitdir for a submodule (given relative to the main
 * repository worktree) into `buf`, or return -1 on error.
 */
int submodule_to_gitdir(struct strbuf *buf, const char *submodule)
{}

void submodule_name_to_gitdir(struct strbuf *buf, struct repository *r,
			      const char *submodule_name)
{}