@@ -2748,7 +2748,7 @@ struct add_data {
2748
2748
const char * prefix ;
2749
2749
const char * branch ;
2750
2750
const char * reference_path ;
2751
- const char * sm_path ;
2751
+ char * sm_path ;
2752
2752
const char * sm_name ;
2753
2753
const char * repo ;
2754
2754
const char * realrepo ;
@@ -3047,6 +3047,168 @@ static int add_config(int argc, const char **argv, const char *prefix)
3047
3047
return 0 ;
3048
3048
}
3049
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
+
3050
3212
#define SUPPORT_SUPER_PREFIX (1<<0)
3051
3213
3052
3214
struct cmd_struct {
@@ -3061,6 +3223,7 @@ static struct cmd_struct commands[] = {
3061
3223
{"clone" , module_clone , 0 },
3062
3224
{"add-clone" , add_clone , 0 },
3063
3225
{"add-config" , add_config , 0 },
3226
+ {"add" , module_add , SUPPORT_SUPER_PREFIX },
3064
3227
{"update-module-mode" , module_update_module_mode , 0 },
3065
3228
{"update-clone" , update_clone , 0 },
3066
3229
{"ensure-core-worktree" , ensure_core_worktree , 0 },
0 commit comments