From: Prathamesh Chavan <pc44800@gmail.com>
To: git@vger.kernel.org
Cc: sbeller@google.com, christian.couder@gmail.com,
Prathamesh Chavan <pc44800@gmail.com>
Subject: [GSoC][PATCH 6/6] submodule: port submodule subcommand 'deinit' from shell to C
Date: Tue, 20 Jun 2017 03:20:25 +0530 [thread overview]
Message-ID: <20170619215025.10086-6-pc44800@gmail.com> (raw)
In-Reply-To: <20170619215025.10086-1-pc44800@gmail.com>
The same mechanism is used even for porting this submodule
subcommand, as used in the ported subcommands till now.
The function cmd_deinit in split up after porting into three
functions: module_deinit, for_each_submodule_list and
deinit_submodule.
Mentored-by: Christian Couder <christian.couder@gmail.com>
Mentored-by: Stefan Beller <sbeller@google.com>
Signed-off-by: Prathamesh Chavan <pc44800@gmail.com>
---
builtin/submodule--helper.c | 140 ++++++++++++++++++++++++++++++++++++++++++++
git-submodule.sh | 55 +----------------
2 files changed, 141 insertions(+), 54 deletions(-)
diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
index e10cac462..f029f5fae 100644
--- a/builtin/submodule--helper.c
+++ b/builtin/submodule--helper.c
@@ -750,6 +750,145 @@ static int module_status(int argc, const char **argv, const char *prefix)
return 0;
}
+struct deinit_cb {
+ const char *prefix;
+ unsigned int quiet: 1;
+ unsigned int force: 1;
+ unsigned int all: 1;
+};
+#define DEINIT_CB_INIT { NULL, 0, 0, 0 }
+
+static void deinit_submodule(const struct cache_entry *list_item,
+ void *cb_data)
+{
+ struct deinit_cb *info = cb_data;
+ const struct submodule *sub;
+ char *displaypath = NULL;
+ struct child_process cp_config = CHILD_PROCESS_INIT;
+ struct strbuf sb_config = STRBUF_INIT;
+ char *sm_path = xstrdup(list_item->name);
+ char *sub_git_dir = xstrfmt("%s/.git", sm_path);
+
+ sub = submodule_from_path(null_sha1, sm_path);
+
+ if (!sub->name)
+ goto cleanup;
+
+ displaypath = get_submodule_displaypath(sm_path, info->prefix);
+
+ /* remove the submodule work tree (unless the user already did it) */
+ if (is_directory(sm_path)) {
+ struct child_process cp = CHILD_PROCESS_INIT;
+
+ /* protect submodules containing a .git directory */
+ if (is_git_directory(sub_git_dir))
+ die(_("Submodule work tree '%s' contains a .git "
+ "directory use 'rm -rf' if you really want "
+ "to remove it including all of its history"),
+ displaypath);
+
+ if (!info->force) {
+ struct child_process cp_rm = CHILD_PROCESS_INIT;
+ cp_rm.git_cmd = 1;
+ argv_array_pushl(&cp_rm.args, "rm", "-qn", sm_path,
+ NULL);
+
+ /* list_item->name is changed by cmd_rm() below */
+ if (run_command(&cp_rm))
+ die(_("Submodule work tree '%s' contains local "
+ "modifications; use '-f' to discard them"),
+ displaypath);
+ }
+
+ cp.use_shell = 1;
+ argv_array_pushl(&cp.args, "rm", "-rf", sm_path, NULL);
+ if (!run_command(&cp)) {
+ if (!info->quiet)
+ printf(_("Cleared directory '%s'\n"),
+ displaypath);
+ } else {
+ if (!info->quiet)
+ printf(_("Could not remove submodule work tree '%s'\n"),
+ displaypath);
+ }
+ }
+
+ if (mkdir(sm_path, 0700))
+ die(_("could not create empty submodule directory %s"),
+ displaypath);
+
+ cp_config.git_cmd = 1;
+ argv_array_pushl(&cp_config.args, "config", "--get-regexp", NULL);
+ argv_array_pushf(&cp_config.args, "submodule.%s\\.", sub->name);
+
+ /* remove the .git/config entries (unless the user already did it) */
+ if (!capture_command(&cp_config, &sb_config, 0) && sb_config.len) {
+ char *sub_key = xstrfmt("submodule.%s", sub->name);
+ /*
+ * remove the whole section so we have a clean state when
+ * the user later decides to init this submodule again
+ */
+ git_config_rename_section_in_file(NULL, sub_key, NULL);
+ if (!info->quiet)
+ printf(_("Submodule '%s' (%s) unregistered for path '%s'\n"),
+ sub->name, sub->url, displaypath);
+ free(sub_key);
+ }
+
+cleanup:
+ free(displaypath);
+ free(sub_git_dir);
+ free(sm_path);
+ strbuf_release(&sb_config);
+}
+
+static int module_deinit(int argc, const char **argv, const char *prefix)
+{
+ struct deinit_cb info = DEINIT_CB_INIT;
+ struct pathspec pathspec;
+ struct module_list list = MODULE_LIST_INIT;
+ int quiet = 0;
+ int force = 0;
+ int all = 0;
+
+ struct option module_deinit_options[] = {
+ OPT__QUIET(&quiet, N_("Suppress submodule status output")),
+ OPT__FORCE(&force, N_("Remove submodule working trees even if they contain local changes")),
+ OPT_BOOL(0, "all", &all, N_("Unregister all submodules")),
+ OPT_END()
+ };
+
+ const char *const git_submodule_helper_usage[] = {
+ N_("git submodule deinit [--quiet] [-f | --force] [--all | [--] [<path>...]]"),
+ NULL
+ };
+
+ argc = parse_options(argc, argv, prefix, module_deinit_options,
+ git_submodule_helper_usage, 0);
+
+ if (module_list_compute(argc, argv, prefix, &pathspec, &list) < 0)
+ BUG("module_list_compute should not choke on empty pathspec");
+
+ info.prefix = prefix;
+ info.quiet = !!quiet;
+ info.all = !!all;
+ info.force = !!force;
+
+ if (all && argc) {
+ error("pathspec and --all are incompatible");
+ usage_with_options(git_submodule_helper_usage,
+ module_deinit_options);
+ }
+
+ if (!argc && !all)
+ die(_("Use '--all' if you really want to deinitialize all submodules"));
+
+ gitmodules_config();
+ for_each_submodule_list(list, deinit_submodule, &info);
+
+ return 0;
+}
+
static int module_name(int argc, const char **argv, const char *prefix)
{
const struct submodule *sub;
@@ -1644,6 +1783,7 @@ static struct cmd_struct commands[] = {
{"status", module_status, SUPPORT_SUPER_PREFIX},
{"print-default-remote", print_default_remote, 0},
{"sync", module_sync, SUPPORT_SUPER_PREFIX},
+ {"deinit", module_deinit, SUPPORT_SUPER_PREFIX},
{"remote-branch", resolve_remote_submodule_branch, 0},
{"push-check", push_check, 0},
{"absorb-git-dirs", absorb_git_dirs, SUPPORT_SUPER_PREFIX},
diff --git a/git-submodule.sh b/git-submodule.sh
index 33b4b7306..2b2c6f5da 100755
--- a/git-submodule.sh
+++ b/git-submodule.sh
@@ -427,60 +427,7 @@ cmd_deinit()
shift
done
- if test -n "$deinit_all" && test "$#" -ne 0
- then
- echo >&2 "$(eval_gettext "pathspec and --all are incompatible")"
- usage
- fi
- if test $# = 0 && test -z "$deinit_all"
- then
- die "$(eval_gettext "Use '--all' if you really want to deinitialize all submodules")"
- fi
-
- {
- git submodule--helper list --prefix "$wt_prefix" "$@" ||
- echo "#unmatched" $?
- } |
- while read -r mode sha1 stage sm_path
- do
- die_if_unmatched "$mode" "$sha1"
- name=$(git submodule--helper name "$sm_path") || exit
-
- displaypath=$(git submodule--helper relative-path "$sm_path" "$wt_prefix")
-
- # Remove the submodule work tree (unless the user already did it)
- if test -d "$sm_path"
- then
- # Protect submodules containing a .git directory
- if test -d "$sm_path/.git"
- then
- die "$(eval_gettext "\
-Submodule work tree '\$displaypath' contains a .git directory
-(use 'rm -rf' if you really want to remove it including all of its history)")"
- fi
-
- if test -z "$force"
- then
- git rm -qn "$sm_path" ||
- die "$(eval_gettext "Submodule work tree '\$displaypath' contains local modifications; use '-f' to discard them")"
- fi
- rm -rf "$sm_path" &&
- say "$(eval_gettext "Cleared directory '\$displaypath'")" ||
- say "$(eval_gettext "Could not remove submodule work tree '\$displaypath'")"
- fi
-
- mkdir "$sm_path" || say "$(eval_gettext "Could not create empty submodule directory '\$displaypath'")"
-
- # Remove the .git/config entries (unless the user already did it)
- if test -n "$(git config --get-regexp submodule."$name\.")"
- then
- # Remove the whole section so we have a clean state when
- # the user later decides to init this submodule again
- url=$(git config submodule."$name".url)
- git config --remove-section submodule."$name" 2>/dev/null &&
- say "$(eval_gettext "Submodule '\$name' (\$url) unregistered for path '\$displaypath'")"
- fi
- done
+ git ${wt_prefix:+-C "$wt_prefix"} submodule--helper deinit ${GIT_QUIET:+--quiet} ${prefix:+--prefix "$prefix"} ${force:+--force} ${deinit_all:+--all} "$@"
}
is_tip_reachable () (
--
2.13.0
next prev parent reply other threads:[~2017-06-19 21:51 UTC|newest]
Thread overview: 16+ messages / expand[flat|nested] mbox.gz Atom feed top
2017-06-19 21:41 [GSoC] Update: Week 5 Prathamesh Chavan
2017-06-19 21:50 ` [GSoC][PATCH 1/6] dir: create function count_slashes Prathamesh Chavan
2017-06-19 21:50 ` [GSoC][PATCH 2/6] submodule--helper: introduce get_submodule_displaypath and for_each_submodule_list Prathamesh Chavan
2017-06-20 18:22 ` Brandon Williams
2017-06-22 7:01 ` Christian Couder
2017-06-19 21:50 ` [GSoC][PATCH 3/6] submodule: port set_name_rev from shell to C Prathamesh Chavan
2017-06-19 21:50 ` [GSoC][PATCH 4/6] submodule: port submodule subcommand status Prathamesh Chavan
2017-06-20 18:44 ` Brandon Williams
2017-06-19 21:50 ` [GSoC][PATCH 5/6] submodule: port submodule subcommand sync from shell to C Prathamesh Chavan
2017-06-20 17:35 ` Stefan Beller
2017-06-22 6:50 ` Christian Couder
2017-06-19 21:50 ` Prathamesh Chavan [this message]
2017-06-20 17:20 ` [GSoC][PATCH 1/6] dir: create function count_slashes Stefan Beller
2017-06-20 0:01 ` [GSoC] Update: Week 5 Andrew Ardill
2017-06-20 0:38 ` Brandon Williams
2017-06-26 23:24 ` Prathamesh Chavan
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20170619215025.10086-6-pc44800@gmail.com \
--to=pc44800@gmail.com \
--cc=christian.couder@gmail.com \
--cc=git@vger.kernel.org \
--cc=sbeller@google.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.