2748
const char *prefix;
2749
const char *branch;
2750
const char *reference_path;
2751
- const char *sm_path;
2751
+ char *sm_path;
2752
const char *sm_name;
2753
const char *repo;
2754
const char *realrepo;
3047
return 0;
3048
}
3049
3050
+static void die_on_index_match(const char *path, int force)
3051
+{
3052
+ struct pathspec ps;
3053
+ const char *args[] = { path, NULL };
3054
+ parse_pathspec(&ps, 0, PATHSPEC_PREFER_CWD, NULL, args);
3055
+
3056
+ if (read_cache_preload(NULL) < 0)
3057
+ die(_("index file corrupt"));
3058
+
3059
+ if (ps.nr) {
3060
+ int i;
3061
+ char *ps_matched = xcalloc(ps.nr, 1);
3062
+
3063
+ /* TODO: audit for interaction with sparse-index. */
3064
+ ensure_full_index(&the_index);
3065
+
3066
+ /*
3067
+ * Since there is only one pathspec, we just need
3068
+ * need to check ps_matched[0] to know if a cache
3069
+ * entry matched.
3070
+ */
3071
+ for (i = 0; i < active_nr; i++) {
3072
+ ce_path_match(&the_index, active_cache[i], &ps,
3073
+ ps_matched);
3074
+
3075
+ if (ps_matched[0]) {
3076
+ if (!force)
3077
+ die(_("'%s' already exists in the index"),
3078
+ path);
3079
+ if (!S_ISGITLINK(active_cache[i]->ce_mode))
3080
+ die(_("'%s' already exists in the index "
3081
+ "and is not a submodule"), path);
3082
+ break;
3083
+ }
3084
+ }
3085
+ free(ps_matched);
3086
+ }
3087
+}
3088
+
3089
+static void die_on_repo_without_commits(const char *path)
3090
+{
3091
+ struct strbuf sb = STRBUF_INIT;
3092
+ strbuf_addstr(&sb, path);
3093
+ if (is_nonbare_repository_dir(&sb)) {
3094
+ struct object_id oid;
3095
+ if (resolve_gitlink_ref(path, "HEAD", &oid) < 0)
3096
+ die(_("'%s' does not have a commit checked out"), path);
3097
+ }
3098
+}
3099
+
3100
+static int module_add(int argc, const char **argv, const char *prefix)
3101
+{
3102
+ int force = 0, quiet = 0, progress = 0, dissociate = 0;
3103
+ struct add_data add_data = ADD_DATA_INIT;
3104
+
3105
+ struct option options[] = {
3106
+ OPT_STRING('b', "branch", &add_data.branch, N_("branch"),
3107
+ N_("branch of repository to add as submodule")),
3108
+ OPT__FORCE(&force, N_("allow adding an otherwise ignored submodule path"),
3109
+ PARSE_OPT_NOCOMPLETE),
3110
+ OPT__QUIET(&quiet, N_("print only error messages")),
3111
+ OPT_BOOL(0, "progress", &progress, N_("force cloning progress")),
3112
+ OPT_STRING(0, "reference", &add_data.reference_path, N_("repository"),
3113
+ N_("reference repository")),
3114
+ OPT_BOOL(0, "dissociate", &dissociate, N_("borrow the objects from reference repositories")),
3115
+ OPT_STRING(0, "name", &add_data.sm_name, N_("name"),
3116
+ N_("sets the submodule’s name to the given string "
3117
+ "instead of defaulting to its path")),
3118
+ OPT_INTEGER(0, "depth", &add_data.depth, N_("depth for shallow clones")),
3119
+ OPT_END()
3120
+ };
3121
+
3122
+ const char *const usage[] = {
3123
+ N_("git submodule--helper add [<options>] [--] <repository> [<path>]"),
3124
+ NULL
3125
+ };
3126
+
3127
+ argc = parse_options(argc, argv, prefix, options, usage, 0);
3128
+
3129
+ if (!is_writing_gitmodules_ok())
3130
+ die(_("please make sure that the .gitmodules file is in the working tree"));
3131
+
3132
+ if (prefix && *prefix &&
3133
+ add_data.reference_path && !is_absolute_path(add_data.reference_path))
3134
+ add_data.reference_path = xstrfmt("%s%s", prefix, add_data.reference_path);
3135
+
3136
+ if (argc == 0 || argc > 2)
3137
+ usage_with_options(usage, options);
3138
+
3139
+ add_data.repo = argv[0];
3140
+ if (argc == 1)
3141
+ add_data.sm_path = git_url_basename(add_data.repo, 0, 0);
3142
+ else
3143
+ add_data.sm_path = xstrdup(argv[1]);
3144
+
3145
+ if (prefix && *prefix && !is_absolute_path(add_data.sm_path))
3146
+ add_data.sm_path = xstrfmt("%s%s", prefix, add_data.sm_path);
3147
+
3148
+ if (starts_with_dot_dot_slash(add_data.repo) ||
3149
+ starts_with_dot_slash(add_data.repo)) {
3150
+ if (prefix)
3151
+ die(_("Relative path can only be used from the toplevel "
3152
+ "of the working tree"));
3153
+
3154
+ /* dereference source url relative to parent's url */
3155
+ add_data.realrepo = compute_submodule_clone_url(add_data.repo, NULL, 1);
3156
+ } else if (is_dir_sep(add_data.repo[0]) || strchr(add_data.repo, ':')) {
3157
+ add_data.realrepo = add_data.repo;
3158
+ } else {
3159
+ die(_("repo URL: '%s' must be absolute or begin with ./|../"),
3160
+ add_data.repo);
3161
+ }
3162
+
3163
+ /*
3164
+ * normalize path:
3165
+ * multiple //; leading ./; /./; /../;
3166
+ */
3167
+ normalize_path_copy(add_data.sm_path, add_data.sm_path);
3168
+ strip_dir_trailing_slashes(add_data.sm_path);
3169
+
3170
+ die_on_index_match(add_data.sm_path, force);
3171
+ die_on_repo_without_commits(add_data.sm_path);
3172
+
3173
+ if (!force) {
3174
+ int exit_code = -1;
3175
+ struct strbuf sb = STRBUF_INIT;
3176
+ struct child_process cp = CHILD_PROCESS_INIT;
3177
+ cp.git_cmd = 1;
3178
+ cp.no_stdout = 1;
3179
+ strvec_pushl(&cp.args, "add", "--dry-run", "--ignore-missing",
3180
+ "--no-warn-embedded-repo", add_data.sm_path, NULL);
3181
+ if ((exit_code = pipe_command(&cp, NULL, 0, NULL, 0, &sb, 0))) {
3182
+ strbuf_complete_line(&sb);
3183
+ fputs(sb.buf, stderr);
3184
+ free(add_data.sm_path);
3185
+ return exit_code;
3186
+ }
3187
+ strbuf_release(&sb);
3188
+ }
3189
+
3190
+ if(!add_data.sm_name)
3191
+ add_data.sm_name = add_data.sm_path;
3192
+
3193
+ if (check_submodule_name(add_data.sm_name))
3194
+ die(_("'%s' is not a valid submodule name"), add_data.sm_name);
3195
+
3196
+ add_data.prefix = prefix;
3197
+ add_data.force = !!force;
3198
+ add_data.quiet = !!quiet;
3199
+ add_data.progress = !!progress;
3200
+ add_data.dissociate = !!dissociate;
3201
+
3202
+ if (add_submodule(&add_data)) {
3203
+ free(add_data.sm_path);
3204
+ return 1;
3205
+ }
3206
+ configure_added_submodule(&add_data);
3207
+ free(add_data.sm_path);
3208
+
3209
+ return 0;
3210
+}
3211
+
3212
#define SUPPORT_SUPER_PREFIX (1<<0)
3213
3214
struct cmd_struct {
3223
{"clone", module_clone, 0},
3224
{"add-clone", add_clone, 0},
3225
{"add-config", add_config, 0},
3226
+ {"add", module_add, SUPPORT_SUPER_PREFIX},
3227
{"update-module-mode", module_update_module_mode, 0},
3228
{"update-clone", update_clone, 0},
3229
{"ensure-core-worktree", ensure_core_worktree, 0},