Carlos Rica | 62e09ce | 2007-07-20 01:42:28 +0200 | [diff] [blame] | 1 | /* |
| 2 | * Builtin "git tag" |
| 3 | * |
| 4 | * Copyright (c) 2007 Kristian Høgsberg <krh@redhat.com>, |
| 5 | * Carlos Rica <jasampler@gmail.com> |
| 6 | * Based on git-tag.sh and mktag.c by Linus Torvalds. |
| 7 | */ |
| 8 | |
| 9 | #include "cache.h" |
| 10 | #include "builtin.h" |
| 11 | #include "refs.h" |
| 12 | #include "tag.h" |
| 13 | #include "run-command.h" |
Carlos Rica | 3968658 | 2007-11-09 14:42:56 +0100 | [diff] [blame] | 14 | #include "parse-options.h" |
Jeff King | ffc4b80 | 2011-06-11 19:04:08 +0000 | [diff] [blame] | 15 | #include "diff.h" |
| 16 | #include "revision.h" |
Junio C Hamano | 2f47eae | 2011-09-07 21:19:47 -0700 | [diff] [blame] | 17 | #include "gpg-interface.h" |
Tom Grennan | ae7706b | 2012-02-08 15:03:43 -0800 | [diff] [blame] | 18 | #include "sha1-array.h" |
Nguyễn Thái Ngọc Duy | d96e3c1 | 2012-04-13 17:54:41 +0700 | [diff] [blame] | 19 | #include "column.h" |
Carlos Rica | 62e09ce | 2007-07-20 01:42:28 +0200 | [diff] [blame] | 20 | |
Carlos Rica | 3968658 | 2007-11-09 14:42:56 +0100 | [diff] [blame] | 21 | static const char * const git_tag_usage[] = { |
Stephan Beyer | 1b1dd23 | 2008-07-13 15:36:15 +0200 | [diff] [blame] | 22 | "git tag [-a|-s|-u <key-id>] [-f] [-m <msg>|-F <file>] <tagname> [<head>]", |
| 23 | "git tag -d <tagname>...", |
Tom Grennan | ae7706b | 2012-02-08 15:03:43 -0800 | [diff] [blame] | 24 | "git tag -l [-n[<num>]] [--contains <commit>] [--points-at <object>] " |
| 25 | "\n\t\t[<pattern>...]", |
Stephan Beyer | 1b1dd23 | 2008-07-13 15:36:15 +0200 | [diff] [blame] | 26 | "git tag -v <tagname>...", |
Carlos Rica | 3968658 | 2007-11-09 14:42:56 +0100 | [diff] [blame] | 27 | NULL |
| 28 | }; |
Carlos Rica | 62e09ce | 2007-07-20 01:42:28 +0200 | [diff] [blame] | 29 | |
Carlos Rica | 62e09ce | 2007-07-20 01:42:28 +0200 | [diff] [blame] | 30 | struct tag_filter { |
Jeff King | 588d0e8 | 2011-06-20 12:59:28 -0400 | [diff] [blame] | 31 | const char **patterns; |
Carlos Rica | 62e09ce | 2007-07-20 01:42:28 +0200 | [diff] [blame] | 32 | int lines; |
Jake Goulding | 32c35cf | 2009-01-26 09:13:25 -0500 | [diff] [blame] | 33 | struct commit_list *with_commit; |
Carlos Rica | 62e09ce | 2007-07-20 01:42:28 +0200 | [diff] [blame] | 34 | }; |
| 35 | |
Tom Grennan | ae7706b | 2012-02-08 15:03:43 -0800 | [diff] [blame] | 36 | static struct sha1_array points_at; |
Nguyễn Thái Ngọc Duy | d96e3c1 | 2012-04-13 17:54:41 +0700 | [diff] [blame] | 37 | static unsigned int colopts; |
Tom Grennan | ae7706b | 2012-02-08 15:03:43 -0800 | [diff] [blame] | 38 | |
Jeff King | 588d0e8 | 2011-06-20 12:59:28 -0400 | [diff] [blame] | 39 | static int match_pattern(const char **patterns, const char *ref) |
| 40 | { |
| 41 | /* no pattern means match everything */ |
| 42 | if (!*patterns) |
| 43 | return 1; |
| 44 | for (; *patterns; patterns++) |
| 45 | if (!fnmatch(*patterns, ref, 0)) |
| 46 | return 1; |
| 47 | return 0; |
| 48 | } |
| 49 | |
Tom Grennan | ae7706b | 2012-02-08 15:03:43 -0800 | [diff] [blame] | 50 | static const unsigned char *match_points_at(const char *refname, |
| 51 | const unsigned char *sha1) |
| 52 | { |
| 53 | const unsigned char *tagged_sha1 = NULL; |
| 54 | struct object *obj; |
| 55 | |
| 56 | if (sha1_array_lookup(&points_at, sha1) >= 0) |
| 57 | return sha1; |
| 58 | obj = parse_object(sha1); |
| 59 | if (!obj) |
| 60 | die(_("malformed object at '%s'"), refname); |
| 61 | if (obj->type == OBJ_TAG) |
| 62 | tagged_sha1 = ((struct tag *)obj)->tagged->sha1; |
| 63 | if (tagged_sha1 && sha1_array_lookup(&points_at, tagged_sha1) >= 0) |
| 64 | return tagged_sha1; |
| 65 | return NULL; |
| 66 | } |
| 67 | |
Jeff King | ffc4b80 | 2011-06-11 19:04:08 +0000 | [diff] [blame] | 68 | static int in_commit_list(const struct commit_list *want, struct commit *c) |
| 69 | { |
| 70 | for (; want; want = want->next) |
| 71 | if (!hashcmp(want->item->object.sha1, c->object.sha1)) |
| 72 | return 1; |
| 73 | return 0; |
| 74 | } |
| 75 | |
| 76 | static int contains_recurse(struct commit *candidate, |
Junio C Hamano | c6d72c4 | 2011-07-14 11:02:06 -0700 | [diff] [blame] | 77 | const struct commit_list *want) |
Jeff King | ffc4b80 | 2011-06-11 19:04:08 +0000 | [diff] [blame] | 78 | { |
| 79 | struct commit_list *p; |
| 80 | |
| 81 | /* was it previously marked as containing a want commit? */ |
| 82 | if (candidate->object.flags & TMP_MARK) |
| 83 | return 1; |
| 84 | /* or marked as not possibly containing a want commit? */ |
| 85 | if (candidate->object.flags & UNINTERESTING) |
| 86 | return 0; |
| 87 | /* or are we it? */ |
| 88 | if (in_commit_list(want, candidate)) |
| 89 | return 1; |
| 90 | |
| 91 | if (parse_commit(candidate) < 0) |
| 92 | return 0; |
| 93 | |
| 94 | /* Otherwise recurse and mark ourselves for future traversals. */ |
| 95 | for (p = candidate->parents; p; p = p->next) { |
Junio C Hamano | c6d72c4 | 2011-07-14 11:02:06 -0700 | [diff] [blame] | 96 | if (contains_recurse(p->item, want)) { |
Jeff King | ffc4b80 | 2011-06-11 19:04:08 +0000 | [diff] [blame] | 97 | candidate->object.flags |= TMP_MARK; |
| 98 | return 1; |
| 99 | } |
| 100 | } |
| 101 | candidate->object.flags |= UNINTERESTING; |
| 102 | return 0; |
| 103 | } |
| 104 | |
| 105 | static int contains(struct commit *candidate, const struct commit_list *want) |
| 106 | { |
Junio C Hamano | c6d72c4 | 2011-07-14 11:02:06 -0700 | [diff] [blame] | 107 | return contains_recurse(candidate, want); |
Jeff King | ffc4b80 | 2011-06-11 19:04:08 +0000 | [diff] [blame] | 108 | } |
| 109 | |
Jeff King | ca51699 | 2012-02-06 03:13:12 -0500 | [diff] [blame] | 110 | static void show_tag_lines(const unsigned char *sha1, int lines) |
| 111 | { |
| 112 | int i; |
| 113 | unsigned long size; |
| 114 | enum object_type type; |
| 115 | char *buf, *sp, *eol; |
| 116 | size_t len; |
| 117 | |
| 118 | buf = read_sha1_file(sha1, &type, &size); |
Jeff King | fb630e0 | 2012-02-06 03:13:42 -0500 | [diff] [blame] | 119 | if (!buf) |
| 120 | die_errno("unable to read object %s", sha1_to_hex(sha1)); |
Junio C Hamano | 31fd8d7 | 2012-02-06 10:13:27 -0800 | [diff] [blame] | 121 | if (type != OBJ_COMMIT && type != OBJ_TAG) |
| 122 | goto free_return; |
| 123 | if (!size) |
| 124 | die("an empty %s object %s?", |
| 125 | typename(type), sha1_to_hex(sha1)); |
Jeff King | ca51699 | 2012-02-06 03:13:12 -0500 | [diff] [blame] | 126 | |
| 127 | /* skip header */ |
| 128 | sp = strstr(buf, "\n\n"); |
Junio C Hamano | 31fd8d7 | 2012-02-06 10:13:27 -0800 | [diff] [blame] | 129 | if (!sp) |
| 130 | goto free_return; |
| 131 | |
| 132 | /* only take up to "lines" lines, and strip the signature from a tag */ |
| 133 | if (type == OBJ_TAG) |
| 134 | size = parse_signature(buf, size); |
Jeff King | ca51699 | 2012-02-06 03:13:12 -0500 | [diff] [blame] | 135 | for (i = 0, sp += 2; i < lines && sp < buf + size; i++) { |
| 136 | if (i) |
| 137 | printf("\n "); |
| 138 | eol = memchr(sp, '\n', size - (sp - buf)); |
| 139 | len = eol ? eol - sp : size - (sp - buf); |
| 140 | fwrite(sp, len, 1, stdout); |
| 141 | if (!eol) |
| 142 | break; |
| 143 | sp = eol + 1; |
| 144 | } |
Junio C Hamano | 31fd8d7 | 2012-02-06 10:13:27 -0800 | [diff] [blame] | 145 | free_return: |
Jeff King | ca51699 | 2012-02-06 03:13:12 -0500 | [diff] [blame] | 146 | free(buf); |
| 147 | } |
| 148 | |
Carlos Rica | 62e09ce | 2007-07-20 01:42:28 +0200 | [diff] [blame] | 149 | static int show_reference(const char *refname, const unsigned char *sha1, |
| 150 | int flag, void *cb_data) |
| 151 | { |
| 152 | struct tag_filter *filter = cb_data; |
| 153 | |
Jeff King | 588d0e8 | 2011-06-20 12:59:28 -0400 | [diff] [blame] | 154 | if (match_pattern(filter->patterns, refname)) { |
Jake Goulding | 32c35cf | 2009-01-26 09:13:25 -0500 | [diff] [blame] | 155 | if (filter->with_commit) { |
| 156 | struct commit *commit; |
| 157 | |
| 158 | commit = lookup_commit_reference_gently(sha1, 1); |
| 159 | if (!commit) |
| 160 | return 0; |
Jeff King | ffc4b80 | 2011-06-11 19:04:08 +0000 | [diff] [blame] | 161 | if (!contains(commit, filter->with_commit)) |
Jake Goulding | 32c35cf | 2009-01-26 09:13:25 -0500 | [diff] [blame] | 162 | return 0; |
| 163 | } |
| 164 | |
Tom Grennan | ae7706b | 2012-02-08 15:03:43 -0800 | [diff] [blame] | 165 | if (points_at.nr && !match_points_at(refname, sha1)) |
| 166 | return 0; |
| 167 | |
Carlos Rica | 62e09ce | 2007-07-20 01:42:28 +0200 | [diff] [blame] | 168 | if (!filter->lines) { |
| 169 | printf("%s\n", refname); |
| 170 | return 0; |
| 171 | } |
| 172 | printf("%-15s ", refname); |
Jeff King | ca51699 | 2012-02-06 03:13:12 -0500 | [diff] [blame] | 173 | show_tag_lines(sha1, filter->lines); |
Carlos Rica | 62e09ce | 2007-07-20 01:42:28 +0200 | [diff] [blame] | 174 | putchar('\n'); |
Carlos Rica | 62e09ce | 2007-07-20 01:42:28 +0200 | [diff] [blame] | 175 | } |
| 176 | |
| 177 | return 0; |
| 178 | } |
| 179 | |
Jeff King | 588d0e8 | 2011-06-20 12:59:28 -0400 | [diff] [blame] | 180 | static int list_tags(const char **patterns, int lines, |
Jake Goulding | 32c35cf | 2009-01-26 09:13:25 -0500 | [diff] [blame] | 181 | struct commit_list *with_commit) |
Carlos Rica | 62e09ce | 2007-07-20 01:42:28 +0200 | [diff] [blame] | 182 | { |
| 183 | struct tag_filter filter; |
Carlos Rica | 62e09ce | 2007-07-20 01:42:28 +0200 | [diff] [blame] | 184 | |
Jeff King | 588d0e8 | 2011-06-20 12:59:28 -0400 | [diff] [blame] | 185 | filter.patterns = patterns; |
Carlos Rica | 62e09ce | 2007-07-20 01:42:28 +0200 | [diff] [blame] | 186 | filter.lines = lines; |
Jake Goulding | 32c35cf | 2009-01-26 09:13:25 -0500 | [diff] [blame] | 187 | filter.with_commit = with_commit; |
Carlos Rica | 62e09ce | 2007-07-20 01:42:28 +0200 | [diff] [blame] | 188 | |
| 189 | for_each_tag_ref(show_reference, (void *) &filter); |
| 190 | |
Carlos Rica | 62e09ce | 2007-07-20 01:42:28 +0200 | [diff] [blame] | 191 | return 0; |
| 192 | } |
| 193 | |
Carlos Rica | e317cfa | 2007-07-21 14:13:12 +0200 | [diff] [blame] | 194 | typedef int (*each_tag_name_fn)(const char *name, const char *ref, |
Carlos Rica | 62e09ce | 2007-07-20 01:42:28 +0200 | [diff] [blame] | 195 | const unsigned char *sha1); |
| 196 | |
Carlos Rica | e317cfa | 2007-07-21 14:13:12 +0200 | [diff] [blame] | 197 | static int for_each_tag_name(const char **argv, each_tag_name_fn fn) |
Carlos Rica | 62e09ce | 2007-07-20 01:42:28 +0200 | [diff] [blame] | 198 | { |
| 199 | const char **p; |
| 200 | char ref[PATH_MAX]; |
| 201 | int had_error = 0; |
| 202 | unsigned char sha1[20]; |
| 203 | |
| 204 | for (p = argv; *p; p++) { |
| 205 | if (snprintf(ref, sizeof(ref), "refs/tags/%s", *p) |
| 206 | >= sizeof(ref)) { |
Ævar Arnfjörð Bjarmason | d08ebf9 | 2011-02-22 23:42:09 +0000 | [diff] [blame] | 207 | error(_("tag name too long: %.*s..."), 50, *p); |
Carlos Rica | 62e09ce | 2007-07-20 01:42:28 +0200 | [diff] [blame] | 208 | had_error = 1; |
| 209 | continue; |
| 210 | } |
Nguyễn Thái Ngọc Duy | c689332 | 2011-11-13 17:22:14 +0700 | [diff] [blame] | 211 | if (read_ref(ref, sha1)) { |
Ævar Arnfjörð Bjarmason | d08ebf9 | 2011-02-22 23:42:09 +0000 | [diff] [blame] | 212 | error(_("tag '%s' not found."), *p); |
Carlos Rica | 62e09ce | 2007-07-20 01:42:28 +0200 | [diff] [blame] | 213 | had_error = 1; |
| 214 | continue; |
| 215 | } |
| 216 | if (fn(*p, ref, sha1)) |
| 217 | had_error = 1; |
| 218 | } |
| 219 | return had_error; |
| 220 | } |
| 221 | |
| 222 | static int delete_tag(const char *name, const char *ref, |
| 223 | const unsigned char *sha1) |
| 224 | { |
Miklos Vajna | eca35a2 | 2008-10-26 03:33:56 +0100 | [diff] [blame] | 225 | if (delete_ref(ref, sha1, 0)) |
Carlos Rica | 62e09ce | 2007-07-20 01:42:28 +0200 | [diff] [blame] | 226 | return 1; |
Ævar Arnfjörð Bjarmason | d08ebf9 | 2011-02-22 23:42:09 +0000 | [diff] [blame] | 227 | printf(_("Deleted tag '%s' (was %s)\n"), name, find_unique_abbrev(sha1, DEFAULT_ABBREV)); |
Carlos Rica | 62e09ce | 2007-07-20 01:42:28 +0200 | [diff] [blame] | 228 | return 0; |
| 229 | } |
| 230 | |
| 231 | static int verify_tag(const char *name, const char *ref, |
| 232 | const unsigned char *sha1) |
| 233 | { |
Jonathan Nieder | a6ccbbd | 2010-04-15 04:36:25 -0500 | [diff] [blame] | 234 | const char *argv_verify_tag[] = {"verify-tag", |
Carlos Rica | 62e09ce | 2007-07-20 01:42:28 +0200 | [diff] [blame] | 235 | "-v", "SHA1_HEX", NULL}; |
| 236 | argv_verify_tag[2] = sha1_to_hex(sha1); |
| 237 | |
Jonathan Nieder | a6ccbbd | 2010-04-15 04:36:25 -0500 | [diff] [blame] | 238 | if (run_command_v_opt(argv_verify_tag, RUN_GIT_CMD)) |
Ævar Arnfjörð Bjarmason | d08ebf9 | 2011-02-22 23:42:09 +0000 | [diff] [blame] | 239 | return error(_("could not verify the tag '%s'"), name); |
Carlos Rica | 62e09ce | 2007-07-20 01:42:28 +0200 | [diff] [blame] | 240 | return 0; |
| 241 | } |
| 242 | |
Pierre Habouzit | fd17f5b | 2007-09-10 12:35:09 +0200 | [diff] [blame] | 243 | static int do_sign(struct strbuf *buffer) |
Carlos Rica | 62e09ce | 2007-07-20 01:42:28 +0200 | [diff] [blame] | 244 | { |
Junio C Hamano | 2f47eae | 2011-09-07 21:19:47 -0700 | [diff] [blame] | 245 | return sign_buffer(buffer, buffer, get_signing_key()); |
Carlos Rica | 62e09ce | 2007-07-20 01:42:28 +0200 | [diff] [blame] | 246 | } |
| 247 | |
| 248 | static const char tag_template[] = |
Ævar Arnfjörð Bjarmason | 7fbff25 | 2011-02-22 23:42:10 +0000 | [diff] [blame] | 249 | N_("\n" |
Carlos Rica | 62e09ce | 2007-07-20 01:42:28 +0200 | [diff] [blame] | 250 | "#\n" |
| 251 | "# Write a tag message\n" |
Kirill A. Shutemov | d3e0598 | 2011-12-07 05:01:45 +0200 | [diff] [blame] | 252 | "# Lines starting with '#' will be ignored.\n" |
| 253 | "#\n"); |
| 254 | |
| 255 | static const char tag_template_nocleanup[] = |
| 256 | N_("\n" |
| 257 | "#\n" |
| 258 | "# Write a tag message\n" |
| 259 | "# Lines starting with '#' will be kept; you may remove them" |
| 260 | " yourself if you want to.\n" |
Ævar Arnfjörð Bjarmason | 7fbff25 | 2011-02-22 23:42:10 +0000 | [diff] [blame] | 261 | "#\n"); |
Carlos Rica | 62e09ce | 2007-07-20 01:42:28 +0200 | [diff] [blame] | 262 | |
Johannes Schindelin | ef90d6d | 2008-05-14 18:46:53 +0100 | [diff] [blame] | 263 | static int git_tag_config(const char *var, const char *value, void *cb) |
Carlos Rica | 62e09ce | 2007-07-20 01:42:28 +0200 | [diff] [blame] | 264 | { |
Junio C Hamano | 2f47eae | 2011-09-07 21:19:47 -0700 | [diff] [blame] | 265 | int status = git_gpg_config(var, value, cb); |
| 266 | if (status) |
| 267 | return status; |
Nguyễn Thái Ngọc Duy | d96e3c1 | 2012-04-13 17:54:41 +0700 | [diff] [blame] | 268 | if (!prefixcmp(var, "column.")) |
| 269 | return git_column_config(var, value, "tag", &colopts); |
Johannes Schindelin | ef90d6d | 2008-05-14 18:46:53 +0100 | [diff] [blame] | 270 | return git_default_config(var, value, cb); |
Carlos Rica | 62e09ce | 2007-07-20 01:42:28 +0200 | [diff] [blame] | 271 | } |
| 272 | |
Mike Hommey | bab8118 | 2007-11-04 01:11:14 +0100 | [diff] [blame] | 273 | static void write_tag_body(int fd, const unsigned char *sha1) |
| 274 | { |
| 275 | unsigned long size; |
| 276 | enum object_type type; |
Michael J Gruber | e10dfb6 | 2010-11-10 12:17:28 +0100 | [diff] [blame] | 277 | char *buf, *sp; |
Mike Hommey | bab8118 | 2007-11-04 01:11:14 +0100 | [diff] [blame] | 278 | |
| 279 | buf = read_sha1_file(sha1, &type, &size); |
| 280 | if (!buf) |
| 281 | return; |
| 282 | /* skip header */ |
| 283 | sp = strstr(buf, "\n\n"); |
| 284 | |
| 285 | if (!sp || !size || type != OBJ_TAG) { |
| 286 | free(buf); |
| 287 | return; |
| 288 | } |
| 289 | sp += 2; /* skip the 2 LFs */ |
Michael J Gruber | e10dfb6 | 2010-11-10 12:17:28 +0100 | [diff] [blame] | 290 | write_or_die(fd, sp, parse_signature(sp, buf + size - sp)); |
Mike Hommey | bab8118 | 2007-11-04 01:11:14 +0100 | [diff] [blame] | 291 | |
| 292 | free(buf); |
| 293 | } |
| 294 | |
Jeff King | 3927bbe | 2008-12-06 14:40:34 -0500 | [diff] [blame] | 295 | static int build_tag_object(struct strbuf *buf, int sign, unsigned char *result) |
| 296 | { |
| 297 | if (sign && do_sign(buf) < 0) |
Ævar Arnfjörð Bjarmason | d08ebf9 | 2011-02-22 23:42:09 +0000 | [diff] [blame] | 298 | return error(_("unable to sign the tag")); |
Jeff King | 3927bbe | 2008-12-06 14:40:34 -0500 | [diff] [blame] | 299 | if (write_sha1_file(buf->buf, buf->len, tag_type, result) < 0) |
Ævar Arnfjörð Bjarmason | d08ebf9 | 2011-02-22 23:42:09 +0000 | [diff] [blame] | 300 | return error(_("unable to write tag file")); |
Jeff King | 3927bbe | 2008-12-06 14:40:34 -0500 | [diff] [blame] | 301 | return 0; |
| 302 | } |
| 303 | |
Kirill A. Shutemov | d3e0598 | 2011-12-07 05:01:45 +0200 | [diff] [blame] | 304 | struct create_tag_options { |
| 305 | unsigned int message_given:1; |
| 306 | unsigned int sign; |
| 307 | enum { |
| 308 | CLEANUP_NONE, |
| 309 | CLEANUP_SPACE, |
| 310 | CLEANUP_ALL |
| 311 | } cleanup_mode; |
| 312 | }; |
| 313 | |
Carlos Rica | 62e09ce | 2007-07-20 01:42:28 +0200 | [diff] [blame] | 314 | static void create_tag(const unsigned char *object, const char *tag, |
Kirill A. Shutemov | d3e0598 | 2011-12-07 05:01:45 +0200 | [diff] [blame] | 315 | struct strbuf *buf, struct create_tag_options *opt, |
Junio C Hamano | bd46c9a | 2007-11-22 23:16:51 -0800 | [diff] [blame] | 316 | unsigned char *prev, unsigned char *result) |
Carlos Rica | 62e09ce | 2007-07-20 01:42:28 +0200 | [diff] [blame] | 317 | { |
| 318 | enum object_type type; |
Pierre Habouzit | fd17f5b | 2007-09-10 12:35:09 +0200 | [diff] [blame] | 319 | char header_buf[1024]; |
| 320 | int header_len; |
Jeff King | 3927bbe | 2008-12-06 14:40:34 -0500 | [diff] [blame] | 321 | char *path = NULL; |
Carlos Rica | 62e09ce | 2007-07-20 01:42:28 +0200 | [diff] [blame] | 322 | |
| 323 | type = sha1_object_info(object, NULL); |
Carlos Rica | e317cfa | 2007-07-21 14:13:12 +0200 | [diff] [blame] | 324 | if (type <= OBJ_NONE) |
Ævar Arnfjörð Bjarmason | d08ebf9 | 2011-02-22 23:42:09 +0000 | [diff] [blame] | 325 | die(_("bad object type.")); |
Carlos Rica | 62e09ce | 2007-07-20 01:42:28 +0200 | [diff] [blame] | 326 | |
| 327 | header_len = snprintf(header_buf, sizeof(header_buf), |
| 328 | "object %s\n" |
| 329 | "type %s\n" |
| 330 | "tag %s\n" |
| 331 | "tagger %s\n\n", |
| 332 | sha1_to_hex(object), |
| 333 | typename(type), |
| 334 | tag, |
Jeff King | f9bc573 | 2012-05-24 19:28:40 -0400 | [diff] [blame] | 335 | git_committer_info(IDENT_STRICT)); |
Carlos Rica | 62e09ce | 2007-07-20 01:42:28 +0200 | [diff] [blame] | 336 | |
Carlos Rica | e317cfa | 2007-07-21 14:13:12 +0200 | [diff] [blame] | 337 | if (header_len > sizeof(header_buf) - 1) |
Ævar Arnfjörð Bjarmason | d08ebf9 | 2011-02-22 23:42:09 +0000 | [diff] [blame] | 338 | die(_("tag header too big.")); |
Carlos Rica | 62e09ce | 2007-07-20 01:42:28 +0200 | [diff] [blame] | 339 | |
Kirill A. Shutemov | d3e0598 | 2011-12-07 05:01:45 +0200 | [diff] [blame] | 340 | if (!opt->message_given) { |
Carlos Rica | 62e09ce | 2007-07-20 01:42:28 +0200 | [diff] [blame] | 341 | int fd; |
| 342 | |
| 343 | /* write the template message before editing: */ |
Alex Riesen | a4f34cb | 2008-10-27 11:22:09 +0100 | [diff] [blame] | 344 | path = git_pathdup("TAG_EDITMSG"); |
Carlos Rica | 62e09ce | 2007-07-20 01:42:28 +0200 | [diff] [blame] | 345 | fd = open(path, O_CREAT | O_TRUNC | O_WRONLY, 0600); |
| 346 | if (fd < 0) |
Ævar Arnfjörð Bjarmason | d08ebf9 | 2011-02-22 23:42:09 +0000 | [diff] [blame] | 347 | die_errno(_("could not create file '%s'"), path); |
Mike Hommey | bab8118 | 2007-11-04 01:11:14 +0100 | [diff] [blame] | 348 | |
| 349 | if (!is_null_sha1(prev)) |
| 350 | write_tag_body(fd, prev); |
Kirill A. Shutemov | d3e0598 | 2011-12-07 05:01:45 +0200 | [diff] [blame] | 351 | else if (opt->cleanup_mode == CLEANUP_ALL) |
| 352 | write_or_die(fd, _(tag_template), |
| 353 | strlen(_(tag_template))); |
Mike Hommey | bab8118 | 2007-11-04 01:11:14 +0100 | [diff] [blame] | 354 | else |
Kirill A. Shutemov | d3e0598 | 2011-12-07 05:01:45 +0200 | [diff] [blame] | 355 | write_or_die(fd, _(tag_template_nocleanup), |
| 356 | strlen(_(tag_template_nocleanup))); |
Carlos Rica | 62e09ce | 2007-07-20 01:42:28 +0200 | [diff] [blame] | 357 | close(fd); |
| 358 | |
Stephan Beyer | 7198203 | 2008-07-25 18:28:42 +0200 | [diff] [blame] | 359 | if (launch_editor(path, buf, NULL)) { |
| 360 | fprintf(stderr, |
Ævar Arnfjörð Bjarmason | d08ebf9 | 2011-02-22 23:42:09 +0000 | [diff] [blame] | 361 | _("Please supply the message using either -m or -F option.\n")); |
Stephan Beyer | 7198203 | 2008-07-25 18:28:42 +0200 | [diff] [blame] | 362 | exit(1); |
| 363 | } |
Carlos Rica | 62e09ce | 2007-07-20 01:42:28 +0200 | [diff] [blame] | 364 | } |
Carlos Rica | 62e09ce | 2007-07-20 01:42:28 +0200 | [diff] [blame] | 365 | |
Kirill A. Shutemov | d3e0598 | 2011-12-07 05:01:45 +0200 | [diff] [blame] | 366 | if (opt->cleanup_mode != CLEANUP_NONE) |
| 367 | stripspace(buf, opt->cleanup_mode == CLEANUP_ALL); |
Carlos Rica | 62e09ce | 2007-07-20 01:42:28 +0200 | [diff] [blame] | 368 | |
Kirill A. Shutemov | d3e0598 | 2011-12-07 05:01:45 +0200 | [diff] [blame] | 369 | if (!opt->message_given && !buf->len) |
Ævar Arnfjörð Bjarmason | d08ebf9 | 2011-02-22 23:42:09 +0000 | [diff] [blame] | 370 | die(_("no tag message?")); |
Carlos Rica | 62e09ce | 2007-07-20 01:42:28 +0200 | [diff] [blame] | 371 | |
Pierre Habouzit | fd17f5b | 2007-09-10 12:35:09 +0200 | [diff] [blame] | 372 | strbuf_insert(buf, 0, header_buf, header_len); |
Carlos Rica | 62e09ce | 2007-07-20 01:42:28 +0200 | [diff] [blame] | 373 | |
Kirill A. Shutemov | d3e0598 | 2011-12-07 05:01:45 +0200 | [diff] [blame] | 374 | if (build_tag_object(buf, opt->sign, result) < 0) { |
Jeff King | 3927bbe | 2008-12-06 14:40:34 -0500 | [diff] [blame] | 375 | if (path) |
Ævar Arnfjörð Bjarmason | d08ebf9 | 2011-02-22 23:42:09 +0000 | [diff] [blame] | 376 | fprintf(stderr, _("The tag message has been left in %s\n"), |
Jeff King | 3927bbe | 2008-12-06 14:40:34 -0500 | [diff] [blame] | 377 | path); |
| 378 | exit(128); |
| 379 | } |
| 380 | if (path) { |
Alex Riesen | 691f1a2 | 2009-04-29 23:22:56 +0200 | [diff] [blame] | 381 | unlink_or_warn(path); |
Jeff King | 3927bbe | 2008-12-06 14:40:34 -0500 | [diff] [blame] | 382 | free(path); |
| 383 | } |
Carlos Rica | 62e09ce | 2007-07-20 01:42:28 +0200 | [diff] [blame] | 384 | } |
| 385 | |
Junio C Hamano | bd46c9a | 2007-11-22 23:16:51 -0800 | [diff] [blame] | 386 | struct msg_arg { |
| 387 | int given; |
| 388 | struct strbuf buf; |
| 389 | }; |
| 390 | |
| 391 | static int parse_msg_arg(const struct option *opt, const char *arg, int unset) |
| 392 | { |
| 393 | struct msg_arg *msg = opt->value; |
| 394 | |
| 395 | if (!arg) |
| 396 | return -1; |
| 397 | if (msg->buf.len) |
| 398 | strbuf_addstr(&(msg->buf), "\n\n"); |
| 399 | strbuf_addstr(&(msg->buf), arg); |
| 400 | msg->given = 1; |
| 401 | return 0; |
| 402 | } |
| 403 | |
Michael Schubert | 4f0accd | 2011-05-10 01:36:36 +0200 | [diff] [blame] | 404 | static int strbuf_check_tag_ref(struct strbuf *sb, const char *name) |
| 405 | { |
| 406 | if (name[0] == '-') |
Michael Haggerty | 8d9c501 | 2011-09-15 23:10:25 +0200 | [diff] [blame] | 407 | return -1; |
Michael Schubert | 4f0accd | 2011-05-10 01:36:36 +0200 | [diff] [blame] | 408 | |
| 409 | strbuf_reset(sb); |
| 410 | strbuf_addf(sb, "refs/tags/%s", name); |
| 411 | |
Michael Haggerty | 8d9c501 | 2011-09-15 23:10:25 +0200 | [diff] [blame] | 412 | return check_refname_format(sb->buf, 0); |
Michael Schubert | 4f0accd | 2011-05-10 01:36:36 +0200 | [diff] [blame] | 413 | } |
| 414 | |
Ramsay Jones | 0975a50 | 2012-02-13 18:24:41 +0000 | [diff] [blame] | 415 | static int parse_opt_points_at(const struct option *opt __attribute__((unused)), |
Tom Grennan | ae7706b | 2012-02-08 15:03:43 -0800 | [diff] [blame] | 416 | const char *arg, int unset) |
| 417 | { |
| 418 | unsigned char sha1[20]; |
| 419 | |
| 420 | if (unset) { |
| 421 | sha1_array_clear(&points_at); |
| 422 | return 0; |
| 423 | } |
| 424 | if (!arg) |
| 425 | return error(_("switch 'points-at' requires an object")); |
| 426 | if (get_sha1(arg, sha1)) |
| 427 | return error(_("malformed object name '%s'"), arg); |
| 428 | sha1_array_append(&points_at, sha1); |
| 429 | return 0; |
| 430 | } |
| 431 | |
Carlos Rica | 62e09ce | 2007-07-20 01:42:28 +0200 | [diff] [blame] | 432 | int cmd_tag(int argc, const char **argv, const char *prefix) |
| 433 | { |
Brandon Casey | f285a2d | 2008-10-09 14:12:12 -0500 | [diff] [blame] | 434 | struct strbuf buf = STRBUF_INIT; |
Michael Schubert | 4f0accd | 2011-05-10 01:36:36 +0200 | [diff] [blame] | 435 | struct strbuf ref = STRBUF_INIT; |
Carlos Rica | 62e09ce | 2007-07-20 01:42:28 +0200 | [diff] [blame] | 436 | unsigned char object[20], prev[20]; |
Carlos Rica | 62e09ce | 2007-07-20 01:42:28 +0200 | [diff] [blame] | 437 | const char *object_ref, *tag; |
Carlos Rica | 62e09ce | 2007-07-20 01:42:28 +0200 | [diff] [blame] | 438 | struct ref_lock *lock; |
Kirill A. Shutemov | d3e0598 | 2011-12-07 05:01:45 +0200 | [diff] [blame] | 439 | struct create_tag_options opt; |
| 440 | char *cleanup_arg = NULL; |
| 441 | int annotate = 0, force = 0, lines = -1, list = 0, |
| 442 | delete = 0, verify = 0; |
Junio C Hamano | dbd0f5c | 2008-08-06 11:43:47 -0700 | [diff] [blame] | 443 | const char *msgfile = NULL, *keyid = NULL; |
Junio C Hamano | bd46c9a | 2007-11-22 23:16:51 -0800 | [diff] [blame] | 444 | struct msg_arg msg = { 0, STRBUF_INIT }; |
Jake Goulding | 32c35cf | 2009-01-26 09:13:25 -0500 | [diff] [blame] | 445 | struct commit_list *with_commit = NULL; |
Carlos Rica | 3968658 | 2007-11-09 14:42:56 +0100 | [diff] [blame] | 446 | struct option options[] = { |
Michael J Gruber | c97eff5 | 2011-08-28 16:54:29 +0200 | [diff] [blame] | 447 | OPT_BOOLEAN('l', "list", &list, "list tag names"), |
Stephen Boyd | e3a0ca8 | 2009-06-04 16:43:56 -0700 | [diff] [blame] | 448 | { OPTION_INTEGER, 'n', NULL, &lines, "n", |
| 449 | "print <n> lines of each tag message", |
Carlos Rica | 3968658 | 2007-11-09 14:42:56 +0100 | [diff] [blame] | 450 | PARSE_OPT_OPTARG, NULL, 1 }, |
Michael J Gruber | c97eff5 | 2011-08-28 16:54:29 +0200 | [diff] [blame] | 451 | OPT_BOOLEAN('d', "delete", &delete, "delete tags"), |
| 452 | OPT_BOOLEAN('v', "verify", &verify, "verify tags"), |
Carlos Rica | 3968658 | 2007-11-09 14:42:56 +0100 | [diff] [blame] | 453 | |
| 454 | OPT_GROUP("Tag creation options"), |
Michael J Gruber | c97eff5 | 2011-08-28 16:54:29 +0200 | [diff] [blame] | 455 | OPT_BOOLEAN('a', "annotate", &annotate, |
Carlos Rica | 3968658 | 2007-11-09 14:42:56 +0100 | [diff] [blame] | 456 | "annotated tag, needs a message"), |
Michael J Gruber | c97eff5 | 2011-08-28 16:54:29 +0200 | [diff] [blame] | 457 | OPT_CALLBACK('m', "message", &msg, "message", |
Michael J Gruber | 3f40617 | 2011-02-15 14:09:07 +0100 | [diff] [blame] | 458 | "tag message", parse_msg_arg), |
Michael J Gruber | c97eff5 | 2011-08-28 16:54:29 +0200 | [diff] [blame] | 459 | OPT_FILENAME('F', "file", &msgfile, "read message from file"), |
Kirill A. Shutemov | d3e0598 | 2011-12-07 05:01:45 +0200 | [diff] [blame] | 460 | OPT_BOOLEAN('s', "sign", &opt.sign, "annotated and GPG-signed tag"), |
| 461 | OPT_STRING(0, "cleanup", &cleanup_arg, "mode", |
| 462 | "how to strip spaces and #comments from message"), |
Michael J Gruber | c97eff5 | 2011-08-28 16:54:29 +0200 | [diff] [blame] | 463 | OPT_STRING('u', "local-user", &keyid, "key-id", |
Carlos Rica | 3968658 | 2007-11-09 14:42:56 +0100 | [diff] [blame] | 464 | "use another key to sign the tag"), |
René Scharfe | 76946b7 | 2010-11-08 19:01:54 +0100 | [diff] [blame] | 465 | OPT__FORCE(&force, "replace the tag if exists"), |
Nguyễn Thái Ngọc Duy | d96e3c1 | 2012-04-13 17:54:41 +0700 | [diff] [blame] | 466 | OPT_COLUMN(0, "column", &colopts, "show tag list in columns"), |
Jake Goulding | 32c35cf | 2009-01-26 09:13:25 -0500 | [diff] [blame] | 467 | |
| 468 | OPT_GROUP("Tag listing options"), |
| 469 | { |
| 470 | OPTION_CALLBACK, 0, "contains", &with_commit, "commit", |
| 471 | "print only tags that contain the commit", |
| 472 | PARSE_OPT_LASTARG_DEFAULT, |
| 473 | parse_opt_with_commit, (intptr_t)"HEAD", |
| 474 | }, |
Tom Grennan | ae7706b | 2012-02-08 15:03:43 -0800 | [diff] [blame] | 475 | { |
| 476 | OPTION_CALLBACK, 0, "points-at", NULL, "object", |
| 477 | "print only tags of the object", 0, parse_opt_points_at |
| 478 | }, |
Carlos Rica | 3968658 | 2007-11-09 14:42:56 +0100 | [diff] [blame] | 479 | OPT_END() |
| 480 | }; |
| 481 | |
Johannes Schindelin | ef90d6d | 2008-05-14 18:46:53 +0100 | [diff] [blame] | 482 | git_config(git_tag_config, NULL); |
Carlos Rica | 3968658 | 2007-11-09 14:42:56 +0100 | [diff] [blame] | 483 | |
Kirill A. Shutemov | d3e0598 | 2011-12-07 05:01:45 +0200 | [diff] [blame] | 484 | memset(&opt, 0, sizeof(opt)); |
| 485 | |
Stephen Boyd | 3778292 | 2009-05-23 11:53:12 -0700 | [diff] [blame] | 486 | argc = parse_options(argc, argv, prefix, options, git_tag_usage, 0); |
Carlos Rica | 3968658 | 2007-11-09 14:42:56 +0100 | [diff] [blame] | 487 | |
Linus Torvalds | be15f50 | 2007-12-10 20:08:06 -0800 | [diff] [blame] | 488 | if (keyid) { |
Kirill A. Shutemov | d3e0598 | 2011-12-07 05:01:45 +0200 | [diff] [blame] | 489 | opt.sign = 1; |
Junio C Hamano | 2f47eae | 2011-09-07 21:19:47 -0700 | [diff] [blame] | 490 | set_signing_key(keyid); |
Linus Torvalds | be15f50 | 2007-12-10 20:08:06 -0800 | [diff] [blame] | 491 | } |
Kirill A. Shutemov | d3e0598 | 2011-12-07 05:01:45 +0200 | [diff] [blame] | 492 | if (opt.sign) |
Junio C Hamano | c1a41b9 | 2007-11-25 15:21:42 -0800 | [diff] [blame] | 493 | annotate = 1; |
Samuel Tardieu | 6fa8342 | 2008-11-05 00:20:31 +0100 | [diff] [blame] | 494 | if (argc == 0 && !(delete || verify)) |
| 495 | list = 1; |
Junio C Hamano | c1a41b9 | 2007-11-25 15:21:42 -0800 | [diff] [blame] | 496 | |
Samuel Tardieu | 6fa8342 | 2008-11-05 00:20:31 +0100 | [diff] [blame] | 497 | if ((annotate || msg.given || msgfile || force) && |
| 498 | (list || delete || verify)) |
| 499 | usage_with_options(git_tag_usage, options); |
| 500 | |
| 501 | if (list + delete + verify > 1) |
| 502 | usage_with_options(git_tag_usage, options); |
Nguyễn Thái Ngọc Duy | d96e3c1 | 2012-04-13 17:54:41 +0700 | [diff] [blame] | 503 | finalize_colopts(&colopts, -1); |
| 504 | if (list && lines != -1) { |
| 505 | if (explicitly_enable_column(colopts)) |
| 506 | die(_("--column and -n are incompatible")); |
| 507 | colopts = 0; |
| 508 | } |
| 509 | if (list) { |
| 510 | int ret; |
| 511 | if (column_active(colopts)) { |
| 512 | struct column_options copts; |
| 513 | memset(&copts, 0, sizeof(copts)); |
| 514 | copts.padding = 2; |
| 515 | run_column_filter(colopts, &copts); |
| 516 | } |
| 517 | ret = list_tags(argv, lines == -1 ? 0 : lines, with_commit); |
| 518 | if (column_active(colopts)) |
| 519 | stop_column_filter(); |
| 520 | return ret; |
| 521 | } |
Samuel Tardieu | 6fa8342 | 2008-11-05 00:20:31 +0100 | [diff] [blame] | 522 | if (lines != -1) |
Ævar Arnfjörð Bjarmason | d08ebf9 | 2011-02-22 23:42:09 +0000 | [diff] [blame] | 523 | die(_("-n option is only allowed with -l.")); |
Jake Goulding | 32c35cf | 2009-01-26 09:13:25 -0500 | [diff] [blame] | 524 | if (with_commit) |
Ævar Arnfjörð Bjarmason | d08ebf9 | 2011-02-22 23:42:09 +0000 | [diff] [blame] | 525 | die(_("--contains option is only allowed with -l.")); |
Tom Grennan | ae7706b | 2012-02-08 15:03:43 -0800 | [diff] [blame] | 526 | if (points_at.nr) |
| 527 | die(_("--points-at option is only allowed with -l.")); |
Carlos Rica | 3968658 | 2007-11-09 14:42:56 +0100 | [diff] [blame] | 528 | if (delete) |
| 529 | return for_each_tag_name(argv, delete_tag); |
| 530 | if (verify) |
| 531 | return for_each_tag_name(argv, verify_tag); |
| 532 | |
Junio C Hamano | bd46c9a | 2007-11-22 23:16:51 -0800 | [diff] [blame] | 533 | if (msg.given || msgfile) { |
| 534 | if (msg.given && msgfile) |
Ævar Arnfjörð Bjarmason | d08ebf9 | 2011-02-22 23:42:09 +0000 | [diff] [blame] | 535 | die(_("only one -F or -m option is allowed.")); |
Carlos Rica | 3968658 | 2007-11-09 14:42:56 +0100 | [diff] [blame] | 536 | annotate = 1; |
Junio C Hamano | bd46c9a | 2007-11-22 23:16:51 -0800 | [diff] [blame] | 537 | if (msg.given) |
| 538 | strbuf_addbuf(&buf, &(msg.buf)); |
Carlos Rica | 3968658 | 2007-11-09 14:42:56 +0100 | [diff] [blame] | 539 | else { |
| 540 | if (!strcmp(msgfile, "-")) { |
Pierre Habouzit | 387e7e1 | 2007-09-27 15:25:55 +0200 | [diff] [blame] | 541 | if (strbuf_read(&buf, 0, 1024) < 0) |
Ævar Arnfjörð Bjarmason | d08ebf9 | 2011-02-22 23:42:09 +0000 | [diff] [blame] | 542 | die_errno(_("cannot read '%s'"), msgfile); |
Pierre Habouzit | 387e7e1 | 2007-09-27 15:25:55 +0200 | [diff] [blame] | 543 | } else { |
Carlos Rica | 3968658 | 2007-11-09 14:42:56 +0100 | [diff] [blame] | 544 | if (strbuf_read_file(&buf, msgfile, 1024) < 0) |
Ævar Arnfjörð Bjarmason | d08ebf9 | 2011-02-22 23:42:09 +0000 | [diff] [blame] | 545 | die_errno(_("could not open or read '%s'"), |
Thomas Rast | d824cbb | 2009-06-27 17:58:46 +0200 | [diff] [blame] | 546 | msgfile); |
Carlos Rica | 62e09ce | 2007-07-20 01:42:28 +0200 | [diff] [blame] | 547 | } |
Carlos Rica | 62e09ce | 2007-07-20 01:42:28 +0200 | [diff] [blame] | 548 | } |
Carlos Rica | 62e09ce | 2007-07-20 01:42:28 +0200 | [diff] [blame] | 549 | } |
| 550 | |
Carlos Rica | 3968658 | 2007-11-09 14:42:56 +0100 | [diff] [blame] | 551 | tag = argv[0]; |
Carlos Rica | 62e09ce | 2007-07-20 01:42:28 +0200 | [diff] [blame] | 552 | |
Carlos Rica | 3968658 | 2007-11-09 14:42:56 +0100 | [diff] [blame] | 553 | object_ref = argc == 2 ? argv[1] : "HEAD"; |
| 554 | if (argc > 2) |
Ævar Arnfjörð Bjarmason | d08ebf9 | 2011-02-22 23:42:09 +0000 | [diff] [blame] | 555 | die(_("too many params")); |
Carlos Rica | 62e09ce | 2007-07-20 01:42:28 +0200 | [diff] [blame] | 556 | |
| 557 | if (get_sha1(object_ref, object)) |
Ævar Arnfjörð Bjarmason | d08ebf9 | 2011-02-22 23:42:09 +0000 | [diff] [blame] | 558 | die(_("Failed to resolve '%s' as a valid ref."), object_ref); |
Carlos Rica | 62e09ce | 2007-07-20 01:42:28 +0200 | [diff] [blame] | 559 | |
Michael Schubert | 4f0accd | 2011-05-10 01:36:36 +0200 | [diff] [blame] | 560 | if (strbuf_check_tag_ref(&ref, tag)) |
Ævar Arnfjörð Bjarmason | d08ebf9 | 2011-02-22 23:42:09 +0000 | [diff] [blame] | 561 | die(_("'%s' is not a valid tag name."), tag); |
Carlos Rica | 62e09ce | 2007-07-20 01:42:28 +0200 | [diff] [blame] | 562 | |
Nguyễn Thái Ngọc Duy | c689332 | 2011-11-13 17:22:14 +0700 | [diff] [blame] | 563 | if (read_ref(ref.buf, prev)) |
Carlos Rica | 62e09ce | 2007-07-20 01:42:28 +0200 | [diff] [blame] | 564 | hashclr(prev); |
| 565 | else if (!force) |
Ævar Arnfjörð Bjarmason | d08ebf9 | 2011-02-22 23:42:09 +0000 | [diff] [blame] | 566 | die(_("tag '%s' already exists"), tag); |
Carlos Rica | 62e09ce | 2007-07-20 01:42:28 +0200 | [diff] [blame] | 567 | |
Kirill A. Shutemov | d3e0598 | 2011-12-07 05:01:45 +0200 | [diff] [blame] | 568 | opt.message_given = msg.given || msgfile; |
| 569 | |
| 570 | if (!cleanup_arg || !strcmp(cleanup_arg, "strip")) |
| 571 | opt.cleanup_mode = CLEANUP_ALL; |
| 572 | else if (!strcmp(cleanup_arg, "verbatim")) |
| 573 | opt.cleanup_mode = CLEANUP_NONE; |
| 574 | else if (!strcmp(cleanup_arg, "whitespace")) |
| 575 | opt.cleanup_mode = CLEANUP_SPACE; |
| 576 | else |
| 577 | die(_("Invalid cleanup mode %s"), cleanup_arg); |
| 578 | |
Carlos Rica | 62e09ce | 2007-07-20 01:42:28 +0200 | [diff] [blame] | 579 | if (annotate) |
Kirill A. Shutemov | d3e0598 | 2011-12-07 05:01:45 +0200 | [diff] [blame] | 580 | create_tag(object, tag, &buf, &opt, prev, object); |
Carlos Rica | 62e09ce | 2007-07-20 01:42:28 +0200 | [diff] [blame] | 581 | |
Michael Schubert | 4f0accd | 2011-05-10 01:36:36 +0200 | [diff] [blame] | 582 | lock = lock_any_ref_for_update(ref.buf, prev, 0); |
Carlos Rica | 62e09ce | 2007-07-20 01:42:28 +0200 | [diff] [blame] | 583 | if (!lock) |
Michael Schubert | 4f0accd | 2011-05-10 01:36:36 +0200 | [diff] [blame] | 584 | die(_("%s: cannot lock the ref"), ref.buf); |
Carlos Rica | 62e09ce | 2007-07-20 01:42:28 +0200 | [diff] [blame] | 585 | if (write_ref_sha1(lock, object, NULL) < 0) |
Michael Schubert | 4f0accd | 2011-05-10 01:36:36 +0200 | [diff] [blame] | 586 | die(_("%s: cannot update the ref"), ref.buf); |
Michael J Gruber | 0a043b1 | 2009-12-10 15:01:10 +0100 | [diff] [blame] | 587 | if (force && hashcmp(prev, object)) |
Ævar Arnfjörð Bjarmason | d08ebf9 | 2011-02-22 23:42:09 +0000 | [diff] [blame] | 588 | printf(_("Updated tag '%s' (was %s)\n"), tag, find_unique_abbrev(prev, DEFAULT_ABBREV)); |
Carlos Rica | 62e09ce | 2007-07-20 01:42:28 +0200 | [diff] [blame] | 589 | |
Pierre Habouzit | fd17f5b | 2007-09-10 12:35:09 +0200 | [diff] [blame] | 590 | strbuf_release(&buf); |
Michael Schubert | 4f0accd | 2011-05-10 01:36:36 +0200 | [diff] [blame] | 591 | strbuf_release(&ref); |
Carlos Rica | 62e09ce | 2007-07-20 01:42:28 +0200 | [diff] [blame] | 592 | return 0; |
| 593 | } |