10
#include "builtin.h"
11
#include "refs.h"
12
#include "resolve-undo.h"
13
+#include "parse-options.h"
14
15
/*
16
* Default to not allowing changes to the list of files. The
398
strbuf_release(&uq);
399
}
400
400
-static const char update_index_usage[] =
401
-"git update-index [-q] [--add] [--replace] [--remove] [--unmerged] [--refresh] [--really-refresh] [--cacheinfo] [--chmod=(+|-)x] [--assume-unchanged] [--skip-worktree|--no-skip-worktree] [--info-only] [--force-remove] [--stdin] [--index-info] [--unresolve] [--again | -g] [--ignore-missing] [-z] [--verbose] [--] [<file>...]";
401
+static const char * const update_index_usage[] = {
402
+ "git update-index [options] [--] [<file>...]",
403
+ NULL
404
+};
405
406
static unsigned char head_sha1[20];
407
static unsigned char merge_head_sha1[20];
581
return 0;
582
}
583
584
+struct refresh_params {
585
+ unsigned int flags;
586
+ int *has_errors;
587
+};
588
+
589
+static int refresh(struct refresh_params *o, unsigned int flag)
590
+{
591
+ setup_work_tree();
592
+ *o->has_errors |= refresh_cache(o->flags | flag);
593
+ return 0;
594
+}
595
+
596
+static int refresh_callback(const struct option *opt,
597
+ const char *arg, int unset)
598
+{
599
+ return refresh(opt->value, 0);
600
+}
601
+
602
+static int really_refresh_callback(const struct option *opt,
603
+ const char *arg, int unset)
604
+{
605
+ return refresh(opt->value, REFRESH_REALLY);
606
+}
607
+
608
+static int chmod_callback(const struct option *opt,
609
+ const char *arg, int unset)
610
+{
611
+ char *flip = opt->value;
612
+ if ((arg[0] != '-' && arg[0] != '+') || arg[1] != 'x' || arg[2])
613
+ return error("option 'chmod' expects \"+x\" or \"-x\"");
614
+ *flip = arg[0];
615
+ return 0;
616
+}
617
+
618
+static int resolve_undo_clear_callback(const struct option *opt,
619
+ const char *arg, int unset)
620
+{
621
+ resolve_undo_clear();
622
+ return 0;
623
+}
624
+
625
+static int cacheinfo_callback(struct parse_opt_ctx_t *ctx,
626
+ const struct option *opt, int unset)
627
+{
628
+ unsigned char sha1[20];
629
+ unsigned int mode;
630
+
631
+ if (ctx->argc <= 3)
632
+ return error("option 'cacheinfo' expects three arguments");
633
+ if (strtoul_ui(*++ctx->argv, 8, &mode) ||
634
+ get_sha1_hex(*++ctx->argv, sha1) ||
635
+ add_cacheinfo(mode, sha1, *++ctx->argv, 0))
636
+ die("git update-index: --cacheinfo cannot add %s", *ctx->argv);
637
+ ctx->argc -= 3;
638
+ return 0;
639
+}
640
+
641
+static int stdin_cacheinfo_callback(struct parse_opt_ctx_t *ctx,
642
+ const struct option *opt, int unset)
643
+{
644
+ int *line_termination = opt->value;
645
+
646
+ if (ctx->argc != 1)
647
+ return error("option '%s' must be the last argument", opt->long_name);
648
+ allow_add = allow_replace = allow_remove = 1;
649
+ read_index_info(*line_termination);
650
+ return 0;
651
+}
652
+
653
+static int stdin_callback(struct parse_opt_ctx_t *ctx,
654
+ const struct option *opt, int unset)
655
+{
656
+ int *read_from_stdin = opt->value;
657
+
658
+ if (ctx->argc != 1)
659
+ return error("option '%s' must be the last argument", opt->long_name);
660
+ *read_from_stdin = 1;
661
+ return 0;
662
+}
663
+
664
+static int unresolve_callback(struct parse_opt_ctx_t *ctx,
665
+ const struct option *opt, int flags)
666
+{
667
+ int *has_errors = opt->value;
668
+ const char *prefix = startup_info->prefix;
669
+
670
+ /* consume remaining arguments. */
671
+ *has_errors = do_unresolve(ctx->argc, ctx->argv,
672
+ prefix, prefix ? strlen(prefix) : 0);
673
+ if (*has_errors)
674
+ active_cache_changed = 0;
675
+
676
+ ctx->argv += ctx->argc - 1;
677
+ ctx->argc = 1;
678
+ return 0;
679
+}
680
+
681
+static int reupdate_callback(struct parse_opt_ctx_t *ctx,
682
+ const struct option *opt, int flags)
683
+{
684
+ int *has_errors = opt->value;
685
+ const char *prefix = startup_info->prefix;
686
+
687
+ /* consume remaining arguments. */
688
+ setup_work_tree();
689
+ *has_errors = do_reupdate(ctx->argc, ctx->argv,
690
+ prefix, prefix ? strlen(prefix) : 0);
691
+ if (*has_errors)
692
+ active_cache_changed = 0;
693
+
694
+ ctx->argv += ctx->argc - 1;
695
+ ctx->argc = 1;
696
+ return 0;
697
+}
698
+
699
int cmd_update_index(int argc, const char **argv, const char *prefix)
700
{
583
- int i, newfd, entries, has_errors = 0, line_termination = '\n';
584
- int allow_options = 1;
701
+ int newfd, entries, has_errors = 0, line_termination = '\n';
702
int read_from_stdin = 0;
703
int prefix_length = prefix ? strlen(prefix) : 0;
704
char set_executable_bit = 0;
588
- unsigned int refresh_flags = 0;
705
+ struct refresh_params refresh_args = {0, &has_errors};
706
int lock_error = 0;
707
struct lock_file *lock_file;
708
+ struct parse_opt_ctx_t ctx;
709
+ int parseopt_state = PARSE_OPT_UNKNOWN;
710
+ struct option options[] = {
711
+ OPT_BIT('q', NULL, &refresh_args.flags,
712
+ "continue refresh even when index needs update",
713
+ REFRESH_QUIET),
714
+ OPT_BIT(0, "ignore-submodules", &refresh_args.flags,
715
+ "refresh: ignore submodules",
716
+ REFRESH_IGNORE_SUBMODULES),
717
+ OPT_SET_INT(0, "add", &allow_add,
718
+ "do not ignore new files", 1),
719
+ OPT_SET_INT(0, "replace", &allow_replace,
720
+ "let files replace directories and vice-versa", 1),
721
+ OPT_SET_INT(0, "remove", &allow_remove,
722
+ "notice files missing from worktree", 1),
723
+ OPT_BIT(0, "unmerged", &refresh_args.flags,
724
+ "refresh even if index contains unmerged entries",
725
+ REFRESH_UNMERGED),
726
+ {OPTION_CALLBACK, 0, "refresh", &refresh_args, NULL,
727
+ "refresh stat information",
728
+ PARSE_OPT_NOARG | PARSE_OPT_NONEG,
729
+ refresh_callback},
730
+ {OPTION_CALLBACK, 0, "really-refresh", &refresh_args, NULL,
731
+ "like --refresh, but ignore assume-unchanged setting",
732
+ PARSE_OPT_NOARG | PARSE_OPT_NONEG,
733
+ really_refresh_callback},
734
+ {OPTION_LOWLEVEL_CALLBACK, 0, "cacheinfo", NULL,
735
+ "<mode> <object> <path>",
736
+ "add the specified entry to the index",
737
+ PARSE_OPT_NOARG | /* disallow --cacheinfo=<mode> form */
738
+ PARSE_OPT_NONEG | PARSE_OPT_LITERAL_ARGHELP,
739
+ (parse_opt_cb *) cacheinfo_callback},
740
+ {OPTION_CALLBACK, 0, "chmod", &set_executable_bit, "(+/-)x",
741
+ "override the executable bit of the listed files",
742
+ PARSE_OPT_NONEG | PARSE_OPT_LITERAL_ARGHELP,
743
+ chmod_callback},
744
+ {OPTION_SET_INT, 0, "assume-unchanged", &mark_valid_only, NULL,
745
+ "mark files as \"not changing\"",
746
+ PARSE_OPT_NOARG | PARSE_OPT_NONEG, NULL, MARK_FLAG},
747
+ {OPTION_SET_INT, 0, "no-assume-unchanged", &mark_valid_only, NULL,
748
+ "clear assumed-unchanged bit",
749
+ PARSE_OPT_NOARG | PARSE_OPT_NONEG, NULL, UNMARK_FLAG},
750
+ {OPTION_SET_INT, 0, "skip-worktree", &mark_skip_worktree_only, NULL,
751
+ "mark files as \"index-only\"",
752
+ PARSE_OPT_NOARG | PARSE_OPT_NONEG, NULL, MARK_FLAG},
753
+ {OPTION_SET_INT, 0, "no-skip-worktree", &mark_skip_worktree_only, NULL,
754
+ "clear skip-worktree bit",
755
+ PARSE_OPT_NOARG | PARSE_OPT_NONEG, NULL, UNMARK_FLAG},
756
+ OPT_SET_INT(0, "info-only", &info_only,
757
+ "add to index only; do not add content to object database", 1),
758
+ OPT_SET_INT(0, "force-remove", &force_remove,
759
+ "remove named paths even if present in worktree", 1),
760
+ OPT_SET_INT('z', NULL, &line_termination,
761
+ "with --stdin: input lines are terminated by null bytes", '\0'),
762
+ {OPTION_LOWLEVEL_CALLBACK, 0, "stdin", &read_from_stdin, NULL,
763
+ "read list of paths to be updated from standard input",
764
+ PARSE_OPT_NONEG | PARSE_OPT_NOARG,
765
+ (parse_opt_cb *) stdin_callback},
766
+ {OPTION_LOWLEVEL_CALLBACK, 0, "index-info", &line_termination, NULL,
767
+ "add entries from standard input to the index",
768
+ PARSE_OPT_NONEG | PARSE_OPT_NOARG,
769
+ (parse_opt_cb *) stdin_cacheinfo_callback},
770
+ {OPTION_LOWLEVEL_CALLBACK, 0, "unresolve", &has_errors, NULL,
771
+ "repopulate stages #2 and #3 for the listed paths",
772
+ PARSE_OPT_NONEG | PARSE_OPT_NOARG,
773
+ (parse_opt_cb *) unresolve_callback},
774
+ {OPTION_LOWLEVEL_CALLBACK, 'g', "again", &has_errors, NULL,
775
+ "only update entries that differ from HEAD",
776
+ PARSE_OPT_NONEG | PARSE_OPT_NOARG,
777
+ (parse_opt_cb *) reupdate_callback},
778
+ OPT_BIT(0, "ignore-missing", &refresh_args.flags,
779
+ "ignore files missing from worktree",
780
+ REFRESH_IGNORE_MISSING),
781
+ OPT_SET_INT(0, "verbose", &verbose,
782
+ "report actions to standard output", 1),
783
+ {OPTION_CALLBACK, 0, "clear-resolve-undo", NULL, NULL,
784
+ "(for porcelains) forget saved unresolved conflicts",
785
+ PARSE_OPT_NOARG | PARSE_OPT_NONEG,
786
+ resolve_undo_clear_callback},
787
+ OPT_END()
788
+ };
789
790
git_config(git_default_config, NULL);
791
800
if (entries < 0)
801
die("cache corrupted");
802
605
- for (i = 1 ; i < argc; i++) {
606
- const char *path = argv[i];
607
- const char *p;
803
+ /*
804
+ * Custom copy of parse_options() because we want to handle
805
+ * filename arguments as they come.
806
+ */
807
+ parse_options_start(&ctx, argc, argv, prefix,
808
+ options, PARSE_OPT_STOP_AT_NON_OPTION);
809
+ while (ctx.argc) {
810
+ if (parseopt_state != PARSE_OPT_DONE)
811
+ parseopt_state = parse_options_step(&ctx, options,
812
+ update_index_usage);
813
+ if (!ctx.argc)
814
+ break;
815
+ switch (parseopt_state) {
816
+ case PARSE_OPT_HELP:
817
+ exit(129);
818
+ case PARSE_OPT_NON_OPTION:
819
+ case PARSE_OPT_DONE:
820
+ {
821
+ const char *path = ctx.argv[0];
822
+ const char *p;
823
609
- if (allow_options && *path == '-') {
610
- if (!strcmp(path, "--")) {
611
- allow_options = 0;
612
- continue;
613
- }
614
- if (!strcmp(path, "-q")) {
615
- refresh_flags |= REFRESH_QUIET;
616
- continue;
617
- }
618
- if (!strcmp(path, "--ignore-submodules")) {
619
- refresh_flags |= REFRESH_IGNORE_SUBMODULES;
620
- continue;
621
- }
622
- if (!strcmp(path, "--add")) {
623
- allow_add = 1;
624
- continue;
625
- }
626
- if (!strcmp(path, "--replace")) {
627
- allow_replace = 1;
628
- continue;
629
- }
630
- if (!strcmp(path, "--remove")) {
631
- allow_remove = 1;
632
- continue;
633
- }
634
- if (!strcmp(path, "--unmerged")) {
635
- refresh_flags |= REFRESH_UNMERGED;
636
- continue;
637
- }
638
- if (!strcmp(path, "--refresh")) {
639
- setup_work_tree();
640
- has_errors |= refresh_cache(refresh_flags);
641
- continue;
642
- }
643
- if (!strcmp(path, "--really-refresh")) {
644
- setup_work_tree();
645
- has_errors |= refresh_cache(REFRESH_REALLY | refresh_flags);
646
- continue;
647
- }
648
- if (!strcmp(path, "--cacheinfo")) {
649
- unsigned char sha1[20];
650
- unsigned int mode;
651
-
652
- if (i+3 >= argc)
653
- die("git update-index: --cacheinfo <mode> <sha1> <path>");
654
-
655
- if (strtoul_ui(argv[i+1], 8, &mode) ||
656
- get_sha1_hex(argv[i+2], sha1) ||
657
- add_cacheinfo(mode, sha1, argv[i+3], 0))
658
- die("git update-index: --cacheinfo"
659
- " cannot add %s", argv[i+3]);
660
- i += 3;
661
- continue;
662
- }
663
- if (!strcmp(path, "--chmod=-x") ||
664
- !strcmp(path, "--chmod=+x")) {
665
- if (argc <= i+1)
666
- die("git update-index: %s <path>", path);
667
- set_executable_bit = path[8];
668
- continue;
669
- }
670
- if (!strcmp(path, "--assume-unchanged")) {
671
- mark_valid_only = MARK_FLAG;
672
- continue;
673
- }
674
- if (!strcmp(path, "--no-assume-unchanged")) {
675
- mark_valid_only = UNMARK_FLAG;
676
- continue;
677
- }
678
- if (!strcmp(path, "--no-skip-worktree")) {
679
- mark_skip_worktree_only = UNMARK_FLAG;
680
- continue;
681
- }
682
- if (!strcmp(path, "--skip-worktree")) {
683
- mark_skip_worktree_only = MARK_FLAG;
684
- continue;
685
- }
686
- if (!strcmp(path, "--info-only")) {
687
- info_only = 1;
688
- continue;
689
- }
690
- if (!strcmp(path, "--force-remove")) {
691
- force_remove = 1;
692
- continue;
693
- }
694
- if (!strcmp(path, "-z")) {
695
- line_termination = 0;
696
- continue;
697
- }
698
- if (!strcmp(path, "--stdin")) {
699
- if (i != argc - 1)
700
- die("--stdin must be at the end");
701
- read_from_stdin = 1;
702
- break;
703
- }
704
- if (!strcmp(path, "--index-info")) {
705
- if (i != argc - 1)
706
- die("--index-info must be at the end");
707
- allow_add = allow_replace = allow_remove = 1;
708
- read_index_info(line_termination);
709
- break;
710
- }
711
- if (!strcmp(path, "--unresolve")) {
712
- has_errors = do_unresolve(argc - i, argv + i,
713
- prefix, prefix_length);
714
- if (has_errors)
715
- active_cache_changed = 0;
716
- goto finish;
717
- }
718
- if (!strcmp(path, "--again") || !strcmp(path, "-g")) {
719
- setup_work_tree();
720
- has_errors = do_reupdate(argc - i, argv + i,
721
- prefix, prefix_length);
722
- if (has_errors)
723
- active_cache_changed = 0;
724
- goto finish;
725
- }
726
- if (!strcmp(path, "--ignore-missing")) {
727
- refresh_flags |= REFRESH_IGNORE_MISSING;
728
- continue;
729
- }
730
- if (!strcmp(path, "--verbose")) {
731
- verbose = 1;
732
- continue;
733
- }
734
- if (!strcmp(path, "--clear-resolve-undo")) {
735
- resolve_undo_clear();
736
- continue;
737
- }
738
- if (!strcmp(path, "-h") || !strcmp(path, "--help"))
739
- usage(update_index_usage);
740
- die("unknown option %s", path);
824
+ setup_work_tree();
825
+ p = prefix_path(prefix, prefix_length, path);
826
+ update_one(p, NULL, 0);
827
+ if (set_executable_bit)
828
+ chmod_path(set_executable_bit, p);
829
+ if (p < path || p > path + strlen(path))
830
+ free((char *)p);
831
+ ctx.argc--;
832
+ ctx.argv++;
833
+ break;
834
+ }
835
+ case PARSE_OPT_UNKNOWN:
836
+ if (ctx.argv[0][1] == '-')
837
+ error("unknown option '%s'", ctx.argv[0] + 2);
838
+ else
839
+ error("unknown switch '%c'", *ctx.opt);
840
+ usage_with_options(update_index_usage, options);
841
}
742
- setup_work_tree();
743
- p = prefix_path(prefix, prefix_length, path);
744
- update_one(p, NULL, 0);
745
- if (set_executable_bit)
746
- chmod_path(set_executable_bit, p);
747
- if (p < path || p > path + strlen(path))
748
- free((char *)p);
842
}
843
+ argc = parse_options_end(&ctx);
844
+
845
if (read_from_stdin) {
846
struct strbuf buf = STRBUF_INIT, nbuf = STRBUF_INIT;
847
865
strbuf_release(&buf);
866
}
867
773
- finish:
868
if (active_cache_changed) {
869
if (newfd < 0) {
776
- if (refresh_flags & REFRESH_QUIET)
870
+ if (refresh_args.flags & REFRESH_QUIET)
871
exit(128);
872
unable_to_lock_index_die(get_index_file(), lock_error);
873
}