From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on dcvr.yhbt.net X-Spam-Level: X-Spam-ASN: AS31976 209.132.180.0/23 X-Spam-Status: No, score=-2.6 required=3.0 tests=AWL,BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,FREEMAIL_FORGED_FROMDOMAIN,FREEMAIL_FROM, HEADER_FROM_DIFFERENT_DOMAINS,RCVD_IN_DNSWL_HI,RCVD_IN_SORBS_SPAM, RP_MATCHES_RCVD shortcircuit=no autolearn=no autolearn_force=no version=3.4.0 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by dcvr.yhbt.net (Postfix) with ESMTP id 6DF912047F for ; Sat, 29 Jul 2017 22:24:43 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753150AbdG2WYl (ORCPT ); Sat, 29 Jul 2017 18:24:41 -0400 Received: from mail-pg0-f68.google.com ([74.125.83.68]:34698 "EHLO mail-pg0-f68.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752485AbdG2WYk (ORCPT ); Sat, 29 Jul 2017 18:24:40 -0400 Received: by mail-pg0-f68.google.com with SMTP id v190so26935333pgv.1 for ; Sat, 29 Jul 2017 15:24:40 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=PgX/WWx0NMXAzWGb8SyMflGlQNeTC2XzlTWcO4Hypl0=; b=Cs5yzmKGK2DZzDZbaENUwFh1NJ+uhnE1gUi+5e0Mh5H9KMnDKJbmbFgkhPa8+7kond 37ZS0RHRrkOEJeFXXZ/kS6Trkr4DNeBLumDMKIliXwYgHNqK/x05/O1vRsXaDCfQLavV FB05erx6q+04H5ebDN1QcqGbngM5HB0JJ/p3PEei9YlPdVW56R8t+sjdFMn0PLzS7x4Y If3C1sxjaqngxCFWA/T8Ko6MUH/XRyvoRYrR6rmTnX/WedJvzBmDQCAl/fkP7+yh0kCD EJcZ+DiPWuVW6LG41qXy/SHutKVa0zdfbFyl676d6TNDxDbGruCASHB9y/d6Wcv+yCvD YtLQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=PgX/WWx0NMXAzWGb8SyMflGlQNeTC2XzlTWcO4Hypl0=; b=IN7eTg3BX9TRUV8cloyRYx+jgy8L7SgnqAa6PmorzXNtBM0mLBvxfm8pOTgthAz5c/ mq5X2i9ltS3g+Lij7vqh/BGsoeKBmcl/A/X/e31DaJcTyACqQ925oEkq6DSBNDEwS1PT xzZuk2KvQRM+zoKwdBZRkZ3fr38coKM+gmbAmT/cn57iujdzxwCxoqTk1HlU9KgjXq+e d6Bez9nRrTAkZR0pStlyEAT01Y7BLLUKm6q6TAw1aBclQFU4YB7Yzt2RgQZ62TWcrAMB vf4bRraNc1ORMZnTwHaX3H0S/LasAvGjtGqfw3+HbGeV/LyCWjmvnlPfteOvk8UjaifH 0nCw== X-Gm-Message-State: AIVw111Xsl03UgLNvS7PtFbELiCnGRnaNq7s6epaWSq45s9OQQ4Z+jrO d0GCtIVxBS9oBWb6rhQ= X-Received: by 10.98.64.83 with SMTP id n80mr11107571pfa.225.1501367079642; Sat, 29 Jul 2017 15:24:39 -0700 (PDT) Received: from localhost.localdomain ([47.11.7.4]) by smtp.gmail.com with ESMTPSA id w125sm43476409pfb.117.2017.07.29.15.24.35 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Sat, 29 Jul 2017 15:24:39 -0700 (PDT) From: Prathamesh Chavan To: git@vger.kernel.org Cc: sbeller@google.com, christian.couder@gmail.com, bmwill@google.com, Prathamesh Chavan Subject: [GSoC][PATCH v2 04/13] submodule: port submodule subcommand 'status' from shell to C Date: Sun, 30 Jul 2017 03:53:52 +0530 Message-Id: <20170729222401.12381-5-pc44800@gmail.com> X-Mailer: git-send-email 2.13.0 In-Reply-To: <20170729222401.12381-1-pc44800@gmail.com> References: <20170724203454.13947-1-pc44800@gmail.com> <20170729222401.12381-1-pc44800@gmail.com> Sender: git-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: git@vger.kernel.org This aims to make git-submodule 'status' a built-in. Hence, the function cmd_status() is ported from shell to C. This is done by introducing three functions: module_status(), submodule_status() and print_status(). The function module_status() acts as the front-end of the subcommand. It parses subcommand's options and then calls the function module_list_compute() for computing the list of submodules. Then this functions calls for_each_submodule_list() looping through the list obtained. Then for_each_submodule_list() calls submodule_status() for each of the submodule in its list. The function submodule_status() is responsible for generating the status each submodule it is called for, and then calls print_status(). Finally, the function print_status() handles the printing of submodule's status. Mentored-by: Christian Couder Mentored-by: Stefan Beller Signed-off-by: Prathamesh Chavan --- In this new version, the following changes have been made: * parameters passed to the function print_status() have been changed. Instead of passing char *sub_sha1, instead the object_id is being passed. * Also, since the passed parameter displaypath's value isn't changed by the function, it is passed to the funcition as const char *displaypath instead of char *displaypath. * the output type of the function handle_submodule_head_ref() is changed from strbuf to object_id, as we will use the object_id instead of the hex of sha1 being stored in a struct strbuf. * diff_files_Args is cleared after using it by passing it as args in the function cmd_diff_files. * In the function status_submodule(), for checking if a submodule has merge conflicts, the patch currently checks if the value of any of the ce_flags is non-zero. Currently, I think the we aren't interested in a partiular flag, but I'm not sure on this. * The confusion with displaypath being passed as te super-prefix in many of the ported subcommands may be a result of the fact that the function generating the displaypath: get_submodule_displaypath() uses the super-prefix as simply a path concatenated with the current submodule name to denote our current location. Also, for generating any submodule's displaypath, it would be important to have ".." passed to the submodule, and currently it is possible only via the super-prefix. builtin/submodule--helper.c | 157 ++++++++++++++++++++++++++++++++++++++++++++ git-submodule.sh | 49 +------------- 2 files changed, 158 insertions(+), 48 deletions(-) diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c index 2cb72d68e..0bd969b7c 100644 --- a/builtin/submodule--helper.c +++ b/builtin/submodule--helper.c @@ -561,6 +561,162 @@ static int module_init(int argc, const char **argv, const char *prefix) return 0; } +struct status_cb { + const char *prefix; + unsigned int quiet: 1; + unsigned int recursive: 1; + unsigned int cached: 1; +}; +#define STATUS_CB_INIT { NULL, 0, 0, 0 } + +static void print_status(struct status_cb *info, char state, const char *path, + const struct object_id *oid, const char *displaypath) +{ + if (info->quiet) + return; + + printf("%c%s %s", state, oid_to_hex(oid), displaypath); + + + if (state == ' ' || state == '+') { + struct argv_array name_rev_args = ARGV_ARRAY_INIT; + + argv_array_pushl(&name_rev_args, "print-name-rev", + path, oid_to_hex(oid), NULL); + print_name_rev(name_rev_args.argc, name_rev_args.argv, + info->prefix); + } else { + printf("\n"); + } +} + +static int handle_submodule_head_ref(const char *refname, + const struct object_id *oid, int flags, + void *cb_data) +{ + struct object_id *output = cb_data; + if (oid) + oidcpy(output, oid); + + return 0; +} + +static void status_submodule(const struct cache_entry *list_item, void *cb_data) +{ + struct status_cb *info = cb_data; + char *displaypath; + struct argv_array diff_files_args = ARGV_ARRAY_INIT; + + if (!submodule_from_path(null_sha1, list_item->name)) + die(_("no submodule mapping found in .gitmodules for path '%s'"), + list_item->name); + + displaypath = get_submodule_displaypath(list_item->name, info->prefix); + + trace_printf("the value of flag is %d\n", list_item->ce_flags); + if (list_item->ce_flags) { + trace_printf("for U the value of flag is %d\n", list_item->ce_flags); + print_status(info, 'U', list_item->name, + &null_oid, displaypath); + goto cleanup; + } + + if (!is_submodule_active(the_repository, list_item->name)) { + print_status(info, '-', list_item->name, &list_item->oid, + displaypath); + goto cleanup; + } + + argv_array_pushl(&diff_files_args, "diff-files", + "--ignore-submodules=dirty", "--quiet", "--", + list_item->name, NULL); + + if (!cmd_diff_files(diff_files_args.argc, diff_files_args.argv, + info->prefix)) { + print_status(info, ' ', list_item->name, &list_item->oid, + displaypath); + } else { + if (!info->cached) { + struct object_id oid; + + if (head_ref_submodule(list_item->name, + handle_submodule_head_ref, &oid)) + die(_("could not resolve HEAD ref inside the" + "submodule '%s'"), list_item->name); + + print_status(info, '+', list_item->name, &oid, + displaypath); + } else { + print_status(info, '+', list_item->name, + &list_item->oid, displaypath); + } + } + + if (info->recursive) { + struct child_process cpr = CHILD_PROCESS_INIT; + + cpr.git_cmd = 1; + cpr.dir = list_item->name; + prepare_submodule_repo_env(&cpr.env_array); + + argv_array_pushl(&cpr.args, "--super-prefix", displaypath, + "submodule--helper", "status", "--recursive", + NULL); + + if (info->cached) + argv_array_push(&cpr.args, "--cached"); + + if (info->quiet) + argv_array_push(&cpr.args, "--quiet"); + + if (run_command(&cpr)) + die(_("failed to recurse into submodule '%s'"), + list_item->name); + } + +cleanup: + argv_array_clear(&diff_files_args); + free(displaypath); +} + +static int module_status(int argc, const char **argv, const char *prefix) +{ + struct status_cb info = STATUS_CB_INIT; + struct pathspec pathspec; + struct module_list list = MODULE_LIST_INIT; + int quiet = 0; + int cached = 0; + int recursive = 0; + + struct option module_status_options[] = { + OPT__QUIET(&quiet, N_("Suppress submodule status output")), + OPT_BOOL(0, "cached", &cached, N_("Use commit stored in the index instead of the one stored in the submodule HEAD")), + OPT_BOOL(0, "recursive", &recursive, N_("Recurse into nested submodules")), + OPT_END() + }; + + const char *const git_submodule_helper_usage[] = { + N_("git submodule status [--quiet] [--cached] [--recursive] []"), + NULL + }; + + argc = parse_options(argc, argv, prefix, module_status_options, + git_submodule_helper_usage, 0); + + if (module_list_compute(argc, argv, prefix, &pathspec, &list) < 0) + return 1; + + info.prefix = prefix; + info.quiet = !!quiet; + info.recursive = !!recursive; + info.cached = !!cached; + + gitmodules_config(); + for_each_submodule_list(list, status_submodule, &info); + + return 0; +} + static int module_name(int argc, const char **argv, const char *prefix) { const struct submodule *sub; @@ -1307,6 +1463,7 @@ static struct cmd_struct commands[] = { {"resolve-relative-url-test", resolve_relative_url_test, 0}, {"print-name-rev", print_name_rev, 0}, {"init", module_init, SUPPORT_SUPER_PREFIX}, + {"status", module_status, 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 e988167e0..51b057d82 100755 --- a/git-submodule.sh +++ b/git-submodule.sh @@ -1005,54 +1005,7 @@ cmd_status() shift done - { - 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 "$prefix$sm_path" "$wt_prefix") - if test "$stage" = U - then - say "U$sha1 $displaypath" - continue - fi - if ! git submodule--helper is-active "$sm_path" || - { - ! test -d "$sm_path"/.git && - ! test -f "$sm_path"/.git - } - then - say "-$sha1 $displaypath" - continue; - fi - if git diff-files --ignore-submodules=dirty --quiet -- "$sm_path" - then - revname=$(git submodule--helper print-name-rev "$sm_path" "$sha1") - say " $sha1 $displaypath$revname" - else - if test -z "$cached" - then - sha1=$(sanitize_submodule_env; cd "$sm_path" && git rev-parse --verify HEAD) - fi - revname=$(git submodule--helper print-name-rev "$sm_path" "$sha1") - say "+$sha1 $displaypath$revname" - fi - - if test -n "$recursive" - then - ( - prefix="$displaypath/" - sanitize_submodule_env - wt_prefix= - cd "$sm_path" && - eval cmd_status - ) || - die "$(eval_gettext "Failed to recurse into submodule path '\$sm_path'")" - fi - done + git ${wt_prefix:+-C "$wt_prefix"} ${prefix:+--super-prefix "$prefix"} submodule--helper status ${GIT_QUIET:+--quiet} ${cached:+--cached} ${recursive:+--recursive} "$@" } # # Sync remote urls for submodules -- 2.13.0