Linus Torvalds | 8bc9a0c | 2005-04-07 15:16:10 -0700 | [diff] [blame] | 1 | /* |
| 2 | * GIT - The information manager from hell |
| 3 | * |
| 4 | * Copyright (C) Linus Torvalds, 2005 |
| 5 | */ |
Junio C Hamano | 4d3fe0c | 2005-09-06 12:53:56 -0700 | [diff] [blame] | 6 | |
Linus Torvalds | e83c516 | 2005-04-07 15:13:13 -0700 | [diff] [blame] | 7 | #include "cache.h" |
Daniel Barkalow | ee6566e | 2005-09-05 02:04:48 -0400 | [diff] [blame] | 8 | #include "object.h" |
| 9 | #include "tree.h" |
Linus Torvalds | 1ccf5a3 | 2006-05-29 12:18:00 -0700 | [diff] [blame] | 10 | #include "tree-walk.h" |
Junio C Hamano | bad68ec | 2006-04-24 21:18:58 -0700 | [diff] [blame] | 11 | #include "cache-tree.h" |
Johannes Schindelin | 16da134 | 2006-07-30 20:25:18 +0200 | [diff] [blame] | 12 | #include "unpack-trees.h" |
Junio C Hamano | f8a9d42 | 2006-12-04 16:00:46 -0800 | [diff] [blame] | 13 | #include "dir.h" |
Peter Eriksen | d147e50 | 2006-05-23 14:15:32 +0200 | [diff] [blame] | 14 | #include "builtin.h" |
Stephen Boyd | 5a56da5 | 2009-06-25 22:14:10 -0700 | [diff] [blame] | 15 | #include "parse-options.h" |
Junio C Hamano | cfc5789 | 2009-12-25 00:30:51 -0800 | [diff] [blame^] | 16 | #include "resolve-undo.h" |
Daniel Barkalow | ee6566e | 2005-09-05 02:04:48 -0400 | [diff] [blame] | 17 | |
Linus Torvalds | 933bf40 | 2007-08-09 22:21:29 -0700 | [diff] [blame] | 18 | static int nr_trees; |
Junio C Hamano | ca885a4 | 2008-03-13 22:07:18 -0700 | [diff] [blame] | 19 | static struct tree *trees[MAX_UNPACK_TREES]; |
Daniel Barkalow | ee6566e | 2005-09-05 02:04:48 -0400 | [diff] [blame] | 20 | |
Daniel Barkalow | ee6566e | 2005-09-05 02:04:48 -0400 | [diff] [blame] | 21 | static int list_tree(unsigned char *sha1) |
| 22 | { |
Linus Torvalds | 933bf40 | 2007-08-09 22:21:29 -0700 | [diff] [blame] | 23 | struct tree *tree; |
| 24 | |
Junio C Hamano | ca885a4 | 2008-03-13 22:07:18 -0700 | [diff] [blame] | 25 | if (nr_trees >= MAX_UNPACK_TREES) |
| 26 | die("I cannot read more than %d trees", MAX_UNPACK_TREES); |
Linus Torvalds | 933bf40 | 2007-08-09 22:21:29 -0700 | [diff] [blame] | 27 | tree = parse_tree_indirect(sha1); |
Daniel Barkalow | ee6566e | 2005-09-05 02:04:48 -0400 | [diff] [blame] | 28 | if (!tree) |
| 29 | return -1; |
Linus Torvalds | 933bf40 | 2007-08-09 22:21:29 -0700 | [diff] [blame] | 30 | trees[nr_trees++] = tree; |
Daniel Barkalow | ee6566e | 2005-09-05 02:04:48 -0400 | [diff] [blame] | 31 | return 0; |
| 32 | } |
| 33 | |
Stephen Boyd | 5a56da5 | 2009-06-25 22:14:10 -0700 | [diff] [blame] | 34 | static const char * const read_tree_usage[] = { |
| 35 | "git read-tree [[-m [--trivial] [--aggressive] | --reset | --prefix=<prefix>] [-u [--exclude-per-directory=<gitignore>] | -i]] [--index-output=<file>] <tree-ish1> [<tree-ish2> [<tree-ish3>]]", |
| 36 | NULL |
| 37 | }; |
| 38 | |
| 39 | static int index_output_cb(const struct option *opt, const char *arg, |
| 40 | int unset) |
| 41 | { |
| 42 | set_alternate_index_output(arg); |
| 43 | return 0; |
| 44 | } |
| 45 | |
| 46 | static int exclude_per_directory_cb(const struct option *opt, const char *arg, |
| 47 | int unset) |
| 48 | { |
| 49 | struct dir_struct *dir; |
| 50 | struct unpack_trees_options *opts; |
| 51 | |
| 52 | opts = (struct unpack_trees_options *)opt->value; |
| 53 | |
| 54 | if (opts->dir) |
| 55 | die("more than one --exclude-per-directory given."); |
| 56 | |
| 57 | dir = xcalloc(1, sizeof(*opts->dir)); |
| 58 | dir->flags |= DIR_SHOW_IGNORED; |
| 59 | dir->exclude_per_dir = arg; |
| 60 | opts->dir = dir; |
| 61 | /* We do not need to nor want to do read-directory |
| 62 | * here; we are merely interested in reusing the |
| 63 | * per directory ignore stack mechanism. |
| 64 | */ |
| 65 | return 0; |
| 66 | } |
Junio C Hamano | c5bac17 | 2005-04-20 19:49:16 -0700 | [diff] [blame] | 67 | |
Junio C Hamano | 021b6e4 | 2006-06-06 12:51:49 -0700 | [diff] [blame] | 68 | static struct lock_file lock_file; |
Junio C Hamano | 96cd542 | 2005-06-06 12:20:55 -0700 | [diff] [blame] | 69 | |
Junio C Hamano | a91af79 | 2006-08-03 13:44:09 -0700 | [diff] [blame] | 70 | int cmd_read_tree(int argc, const char **argv, const char *unused_prefix) |
Linus Torvalds | e83c516 | 2005-04-07 15:13:13 -0700 | [diff] [blame] | 71 | { |
Linus Torvalds | 6d6776c | 2006-05-15 08:09:31 -0700 | [diff] [blame] | 72 | int i, newfd, stage = 0; |
Linus Torvalds | e83c516 | 2005-04-07 15:13:13 -0700 | [diff] [blame] | 73 | unsigned char sha1[20]; |
Junio C Hamano | ca885a4 | 2008-03-13 22:07:18 -0700 | [diff] [blame] | 74 | struct tree_desc t[MAX_UNPACK_TREES]; |
Johannes Schindelin | 16da134 | 2006-07-30 20:25:18 +0200 | [diff] [blame] | 75 | struct unpack_trees_options opts; |
Stephen Boyd | 5a56da5 | 2009-06-25 22:14:10 -0700 | [diff] [blame] | 76 | int prefix_set = 0; |
| 77 | const struct option read_tree_options[] = { |
| 78 | { OPTION_CALLBACK, 0, "index-output", NULL, "FILE", |
| 79 | "write resulting index to <FILE>", |
| 80 | PARSE_OPT_NONEG, index_output_cb }, |
| 81 | OPT__VERBOSE(&opts.verbose_update), |
| 82 | OPT_GROUP("Merging"), |
| 83 | OPT_SET_INT('m', NULL, &opts.merge, |
| 84 | "perform a merge in addition to a read", 1), |
| 85 | OPT_SET_INT(0, "trivial", &opts.trivial_merges_only, |
| 86 | "3-way merge if no file level merging required", 1), |
| 87 | OPT_SET_INT(0, "aggressive", &opts.aggressive, |
| 88 | "3-way merge in presence of adds and removes", 1), |
| 89 | OPT_SET_INT(0, "reset", &opts.reset, |
| 90 | "same as -m, but discard unmerged entries", 1), |
| 91 | { OPTION_STRING, 0, "prefix", &opts.prefix, "<subdirectory>/", |
| 92 | "read the tree into the index under <subdirectory>/", |
| 93 | PARSE_OPT_NONEG | PARSE_OPT_LITERAL_ARGHELP }, |
| 94 | OPT_SET_INT('u', NULL, &opts.update, |
| 95 | "update working tree with merge result", 1), |
| 96 | { OPTION_CALLBACK, 0, "exclude-per-directory", &opts, |
| 97 | "gitignore", |
| 98 | "allow explicitly ignored files to be overwritten", |
| 99 | PARSE_OPT_NONEG, exclude_per_directory_cb }, |
| 100 | OPT_SET_INT('i', NULL, &opts.index_only, |
| 101 | "don't check the working tree after merging", 1), |
| 102 | OPT_END() |
| 103 | }; |
Linus Torvalds | e83c516 | 2005-04-07 15:13:13 -0700 | [diff] [blame] | 104 | |
Johannes Schindelin | 16da134 | 2006-07-30 20:25:18 +0200 | [diff] [blame] | 105 | memset(&opts, 0, sizeof(opts)); |
| 106 | opts.head_idx = -1; |
Linus Torvalds | 34110cd | 2008-03-06 18:12:28 -0800 | [diff] [blame] | 107 | opts.src_index = &the_index; |
| 108 | opts.dst_index = &the_index; |
Shawn Pearce | 344c52a | 2006-07-08 14:34:02 -0400 | [diff] [blame] | 109 | |
Johannes Schindelin | ef90d6d | 2008-05-14 18:46:53 +0100 | [diff] [blame] | 110 | git_config(git_default_config, NULL); |
Junio C Hamano | 53228a5 | 2005-11-26 00:50:02 -0800 | [diff] [blame] | 111 | |
Stephen Boyd | 5a56da5 | 2009-06-25 22:14:10 -0700 | [diff] [blame] | 112 | argc = parse_options(argc, argv, unused_prefix, read_tree_options, |
| 113 | read_tree_usage, 0); |
| 114 | |
Jonathan Nieder | 99caeed | 2009-11-09 09:05:01 -0600 | [diff] [blame] | 115 | newfd = hold_locked_index(&lock_file, 1); |
| 116 | |
Stephen Boyd | 5a56da5 | 2009-06-25 22:14:10 -0700 | [diff] [blame] | 117 | prefix_set = opts.prefix ? 1 : 0; |
| 118 | if (1 < opts.merge + opts.reset + prefix_set) |
| 119 | die("Which one? -m, --reset, or --prefix?"); |
Alexandre Julliard | db137fe | 2009-08-17 17:35:44 +0200 | [diff] [blame] | 120 | |
| 121 | if (opts.reset || opts.merge || opts.prefix) { |
| 122 | if (read_cache_unmerged() && (opts.prefix || opts.merge)) |
| 123 | die("You need to resolve your current index first"); |
| 124 | stage = opts.merge = 1; |
| 125 | } |
Junio C Hamano | cfc5789 | 2009-12-25 00:30:51 -0800 | [diff] [blame^] | 126 | resolve_undo_clear(); |
Stephen Boyd | 5a56da5 | 2009-06-25 22:14:10 -0700 | [diff] [blame] | 127 | |
| 128 | for (i = 0; i < argc; i++) { |
Linus Torvalds | 83adac3 | 2005-04-09 12:11:25 -0700 | [diff] [blame] | 129 | const char *arg = argv[i]; |
| 130 | |
Dmitry V. Levin | 31fff30 | 2006-05-09 01:43:38 +0400 | [diff] [blame] | 131 | if (get_sha1(arg, sha1)) |
| 132 | die("Not a valid object name %s", arg); |
Daniel Barkalow | ee6566e | 2005-09-05 02:04:48 -0400 | [diff] [blame] | 133 | if (list_tree(sha1) < 0) |
Petr Baudis | 2de381f | 2005-04-13 02:28:48 -0700 | [diff] [blame] | 134 | die("failed to unpack tree object %s", arg); |
Linus Torvalds | d99082e | 2005-04-15 22:53:45 -0700 | [diff] [blame] | 135 | stage++; |
Linus Torvalds | 83adac3 | 2005-04-09 12:11:25 -0700 | [diff] [blame] | 136 | } |
Stephen Boyd | 5a56da5 | 2009-06-25 22:14:10 -0700 | [diff] [blame] | 137 | if (1 < opts.index_only + opts.update) |
| 138 | die("-u and -i at the same time makes no sense"); |
Johannes Schindelin | 16da134 | 2006-07-30 20:25:18 +0200 | [diff] [blame] | 139 | if ((opts.update||opts.index_only) && !opts.merge) |
Stephen Boyd | a429d2d | 2009-06-25 22:14:09 -0700 | [diff] [blame] | 140 | die("%s is meaningless without -m, --reset, or --prefix", |
| 141 | opts.update ? "-u" : "-i"); |
Junio C Hamano | f8a9d42 | 2006-12-04 16:00:46 -0800 | [diff] [blame] | 142 | if ((opts.dir && !opts.update)) |
| 143 | die("--exclude-per-directory is meaningless unless -u"); |
Nguyễn Thái Ngọc Duy | b6469a8 | 2008-08-28 20:03:22 +0700 | [diff] [blame] | 144 | if (opts.merge && !opts.index_only) |
| 145 | setup_work_tree(); |
Junio C Hamano | 7dd4357 | 2005-10-02 00:50:16 -0700 | [diff] [blame] | 146 | |
Johannes Schindelin | 16da134 | 2006-07-30 20:25:18 +0200 | [diff] [blame] | 147 | if (opts.merge) { |
Daniel Barkalow | ee6566e | 2005-09-05 02:04:48 -0400 | [diff] [blame] | 148 | if (stage < 2) |
Linus Torvalds | a3a6523 | 2005-04-19 11:41:18 -0700 | [diff] [blame] | 149 | die("just how do you expect me to merge %d trees?", stage-1); |
Daniel Barkalow | ee6566e | 2005-09-05 02:04:48 -0400 | [diff] [blame] | 150 | switch (stage - 1) { |
| 151 | case 1: |
Johannes Schindelin | 16da134 | 2006-07-30 20:25:18 +0200 | [diff] [blame] | 152 | opts.fn = opts.prefix ? bind_merge : oneway_merge; |
Daniel Barkalow | ee6566e | 2005-09-05 02:04:48 -0400 | [diff] [blame] | 153 | break; |
| 154 | case 2: |
Johannes Schindelin | 16da134 | 2006-07-30 20:25:18 +0200 | [diff] [blame] | 155 | opts.fn = twoway_merge; |
Junio C Hamano | fa7b3c2 | 2008-11-12 11:52:35 -0800 | [diff] [blame] | 156 | opts.initial_checkout = is_cache_unborn(); |
Daniel Barkalow | ee6566e | 2005-09-05 02:04:48 -0400 | [diff] [blame] | 157 | break; |
| 158 | case 3: |
Daniel Barkalow | ee6566e | 2005-09-05 02:04:48 -0400 | [diff] [blame] | 159 | default: |
Johannes Schindelin | 16da134 | 2006-07-30 20:25:18 +0200 | [diff] [blame] | 160 | opts.fn = threeway_merge; |
Daniel Barkalow | ee6566e | 2005-09-05 02:04:48 -0400 | [diff] [blame] | 161 | break; |
Junio C Hamano | 03efa6d | 2005-06-10 18:36:08 -0700 | [diff] [blame] | 162 | } |
Daniel Barkalow | ee6566e | 2005-09-05 02:04:48 -0400 | [diff] [blame] | 163 | |
Daniel Barkalow | ee6566e | 2005-09-05 02:04:48 -0400 | [diff] [blame] | 164 | if (stage - 1 >= 3) |
Johannes Schindelin | 16da134 | 2006-07-30 20:25:18 +0200 | [diff] [blame] | 165 | opts.head_idx = stage - 2; |
Daniel Barkalow | ee6566e | 2005-09-05 02:04:48 -0400 | [diff] [blame] | 166 | else |
Johannes Schindelin | 16da134 | 2006-07-30 20:25:18 +0200 | [diff] [blame] | 167 | opts.head_idx = 1; |
Daniel Barkalow | ee6566e | 2005-09-05 02:04:48 -0400 | [diff] [blame] | 168 | } |
| 169 | |
Junio C Hamano | 8cc21ce | 2009-04-20 03:58:17 -0700 | [diff] [blame] | 170 | cache_tree_free(&active_cache_tree); |
Linus Torvalds | 933bf40 | 2007-08-09 22:21:29 -0700 | [diff] [blame] | 171 | for (i = 0; i < nr_trees; i++) { |
| 172 | struct tree *tree = trees[i]; |
| 173 | parse_tree(tree); |
| 174 | init_tree_desc(t+i, tree->buffer, tree->size); |
| 175 | } |
Daniel Barkalow | 203a2fe | 2008-02-07 11:39:48 -0500 | [diff] [blame] | 176 | if (unpack_trees(nr_trees, t, &opts)) |
| 177 | return 128; |
Junio C Hamano | 7927a55 | 2006-04-27 01:33:07 -0700 | [diff] [blame] | 178 | |
| 179 | /* |
| 180 | * When reading only one tree (either the most basic form, |
| 181 | * "-m ent" or "--reset ent" form), we can obtain a fully |
| 182 | * valid cache-tree because the index must match exactly |
| 183 | * what came from the tree. |
Junio C Hamano | 456156d | 2009-04-20 03:58:19 -0700 | [diff] [blame] | 184 | * |
| 185 | * The same holds true if we are switching between two trees |
| 186 | * using read-tree -m A B. The index must match B after that. |
Junio C Hamano | 7927a55 | 2006-04-27 01:33:07 -0700 | [diff] [blame] | 187 | */ |
Junio C Hamano | 8cc21ce | 2009-04-20 03:58:17 -0700 | [diff] [blame] | 188 | if (nr_trees == 1 && !opts.prefix) |
Junio C Hamano | b9d37a5 | 2009-04-20 03:58:18 -0700 | [diff] [blame] | 189 | prime_cache_tree(&active_cache_tree, trees[0]); |
Junio C Hamano | 456156d | 2009-04-20 03:58:19 -0700 | [diff] [blame] | 190 | else if (nr_trees == 2 && opts.merge) |
| 191 | prime_cache_tree(&active_cache_tree, trees[1]); |
Junio C Hamano | 7927a55 | 2006-04-27 01:33:07 -0700 | [diff] [blame] | 192 | |
Junio C Hamano | 96cd542 | 2005-06-06 12:20:55 -0700 | [diff] [blame] | 193 | if (write_cache(newfd, active_cache, active_nr) || |
Brandon Casey | 4ed7cd3 | 2008-01-16 13:12:46 -0600 | [diff] [blame] | 194 | commit_locked_index(&lock_file)) |
Petr Baudis | 2de381f | 2005-04-13 02:28:48 -0700 | [diff] [blame] | 195 | die("unable to write new index file"); |
Linus Torvalds | 9614b8d | 2005-04-11 15:39:26 -0700 | [diff] [blame] | 196 | return 0; |
Linus Torvalds | e83c516 | 2005-04-07 15:13:13 -0700 | [diff] [blame] | 197 | } |