PageRenderTime 81ms CodeModel.GetById 37ms RepoModel.GetById 0ms app.codeStats 0ms

/git-source/contrib/examples/builtin-fetch--tool.c

https://bitbucket.org/pankonrad/git-kata-registration
C | 574 lines | 507 code | 55 blank | 12 comment | 142 complexity | 9c8b9581a055842ee86e9989e3397b6b MD5 | raw file
  1. #include "builtin.h"
  2. #include "cache.h"
  3. #include "refs.h"
  4. #include "commit.h"
  5. #include "sigchain.h"
  6. static char *get_stdin(void)
  7. {
  8. struct strbuf buf = STRBUF_INIT;
  9. if (strbuf_read(&buf, 0, 1024) < 0) {
  10. die_errno("error reading standard input");
  11. }
  12. return strbuf_detach(&buf, NULL);
  13. }
  14. static void show_new(enum object_type type, unsigned char *sha1_new)
  15. {
  16. fprintf(stderr, " %s: %s\n", typename(type),
  17. find_unique_abbrev(sha1_new, DEFAULT_ABBREV));
  18. }
  19. static int update_ref_env(const char *action,
  20. const char *refname,
  21. unsigned char *sha1,
  22. unsigned char *oldval)
  23. {
  24. char msg[1024];
  25. const char *rla = getenv("GIT_REFLOG_ACTION");
  26. if (!rla)
  27. rla = "(reflog update)";
  28. if (snprintf(msg, sizeof(msg), "%s: %s", rla, action) >= sizeof(msg))
  29. warning("reflog message too long: %.*s...", 50, msg);
  30. return update_ref(msg, refname, sha1, oldval, 0, QUIET_ON_ERR);
  31. }
  32. static int update_local_ref(const char *name,
  33. const char *new_head,
  34. const char *note,
  35. int verbose, int force)
  36. {
  37. unsigned char sha1_old[20], sha1_new[20];
  38. char oldh[41], newh[41];
  39. struct commit *current, *updated;
  40. enum object_type type;
  41. if (get_sha1_hex(new_head, sha1_new))
  42. die("malformed object name %s", new_head);
  43. type = sha1_object_info(sha1_new, NULL);
  44. if (type < 0)
  45. die("object %s not found", new_head);
  46. if (!*name) {
  47. /* Not storing */
  48. if (verbose) {
  49. fprintf(stderr, "* fetched %s\n", note);
  50. show_new(type, sha1_new);
  51. }
  52. return 0;
  53. }
  54. if (get_sha1(name, sha1_old)) {
  55. const char *msg;
  56. just_store:
  57. /* new ref */
  58. if (!strncmp(name, "refs/tags/", 10))
  59. msg = "storing tag";
  60. else
  61. msg = "storing head";
  62. fprintf(stderr, "* %s: storing %s\n",
  63. name, note);
  64. show_new(type, sha1_new);
  65. return update_ref_env(msg, name, sha1_new, NULL);
  66. }
  67. if (!hashcmp(sha1_old, sha1_new)) {
  68. if (verbose) {
  69. fprintf(stderr, "* %s: same as %s\n", name, note);
  70. show_new(type, sha1_new);
  71. }
  72. return 0;
  73. }
  74. if (!strncmp(name, "refs/tags/", 10)) {
  75. fprintf(stderr, "* %s: updating with %s\n", name, note);
  76. show_new(type, sha1_new);
  77. return update_ref_env("updating tag", name, sha1_new, NULL);
  78. }
  79. current = lookup_commit_reference(sha1_old);
  80. updated = lookup_commit_reference(sha1_new);
  81. if (!current || !updated)
  82. goto just_store;
  83. strcpy(oldh, find_unique_abbrev(current->object.sha1, DEFAULT_ABBREV));
  84. strcpy(newh, find_unique_abbrev(sha1_new, DEFAULT_ABBREV));
  85. if (in_merge_bases(current, updated)) {
  86. fprintf(stderr, "* %s: fast-forward to %s\n",
  87. name, note);
  88. fprintf(stderr, " old..new: %s..%s\n", oldh, newh);
  89. return update_ref_env("fast-forward", name, sha1_new, sha1_old);
  90. }
  91. if (!force) {
  92. fprintf(stderr,
  93. "* %s: not updating to non-fast-forward %s\n",
  94. name, note);
  95. fprintf(stderr,
  96. " old...new: %s...%s\n", oldh, newh);
  97. return 1;
  98. }
  99. fprintf(stderr,
  100. "* %s: forcing update to non-fast-forward %s\n",
  101. name, note);
  102. fprintf(stderr, " old...new: %s...%s\n", oldh, newh);
  103. return update_ref_env("forced-update", name, sha1_new, sha1_old);
  104. }
  105. static int append_fetch_head(FILE *fp,
  106. const char *head, const char *remote,
  107. const char *remote_name, const char *remote_nick,
  108. const char *local_name, int not_for_merge,
  109. int verbose, int force)
  110. {
  111. struct commit *commit;
  112. int remote_len, i, note_len;
  113. unsigned char sha1[20];
  114. char note[1024];
  115. const char *what, *kind;
  116. if (get_sha1(head, sha1))
  117. return error("Not a valid object name: %s", head);
  118. commit = lookup_commit_reference_gently(sha1, 1);
  119. if (!commit)
  120. not_for_merge = 1;
  121. if (!strcmp(remote_name, "HEAD")) {
  122. kind = "";
  123. what = "";
  124. }
  125. else if (!strncmp(remote_name, "refs/heads/", 11)) {
  126. kind = "branch";
  127. what = remote_name + 11;
  128. }
  129. else if (!strncmp(remote_name, "refs/tags/", 10)) {
  130. kind = "tag";
  131. what = remote_name + 10;
  132. }
  133. else if (!strncmp(remote_name, "refs/remotes/", 13)) {
  134. kind = "remote-tracking branch";
  135. what = remote_name + 13;
  136. }
  137. else {
  138. kind = "";
  139. what = remote_name;
  140. }
  141. remote_len = strlen(remote);
  142. for (i = remote_len - 1; remote[i] == '/' && 0 <= i; i--)
  143. ;
  144. remote_len = i + 1;
  145. if (4 < i && !strncmp(".git", remote + i - 3, 4))
  146. remote_len = i - 3;
  147. note_len = 0;
  148. if (*what) {
  149. if (*kind)
  150. note_len += sprintf(note + note_len, "%s ", kind);
  151. note_len += sprintf(note + note_len, "'%s' of ", what);
  152. }
  153. note_len += sprintf(note + note_len, "%.*s", remote_len, remote);
  154. fprintf(fp, "%s\t%s\t%s\n",
  155. sha1_to_hex(commit ? commit->object.sha1 : sha1),
  156. not_for_merge ? "not-for-merge" : "",
  157. note);
  158. return update_local_ref(local_name, head, note, verbose, force);
  159. }
  160. static char *keep;
  161. static void remove_keep(void)
  162. {
  163. if (keep && *keep)
  164. unlink(keep);
  165. }
  166. static void remove_keep_on_signal(int signo)
  167. {
  168. remove_keep();
  169. sigchain_pop(signo);
  170. raise(signo);
  171. }
  172. static char *find_local_name(const char *remote_name, const char *refs,
  173. int *force_p, int *not_for_merge_p)
  174. {
  175. const char *ref = refs;
  176. int len = strlen(remote_name);
  177. while (ref) {
  178. const char *next;
  179. int single_force, not_for_merge;
  180. while (*ref == '\n')
  181. ref++;
  182. if (!*ref)
  183. break;
  184. next = strchr(ref, '\n');
  185. single_force = not_for_merge = 0;
  186. if (*ref == '+') {
  187. single_force = 1;
  188. ref++;
  189. }
  190. if (*ref == '.') {
  191. not_for_merge = 1;
  192. ref++;
  193. if (*ref == '+') {
  194. single_force = 1;
  195. ref++;
  196. }
  197. }
  198. if (!strncmp(remote_name, ref, len) && ref[len] == ':') {
  199. const char *local_part = ref + len + 1;
  200. int retlen;
  201. if (!next)
  202. retlen = strlen(local_part);
  203. else
  204. retlen = next - local_part;
  205. *force_p = single_force;
  206. *not_for_merge_p = not_for_merge;
  207. return xmemdupz(local_part, retlen);
  208. }
  209. ref = next;
  210. }
  211. return NULL;
  212. }
  213. static int fetch_native_store(FILE *fp,
  214. const char *remote,
  215. const char *remote_nick,
  216. const char *refs,
  217. int verbose, int force)
  218. {
  219. char buffer[1024];
  220. int err = 0;
  221. sigchain_push_common(remove_keep_on_signal);
  222. atexit(remove_keep);
  223. while (fgets(buffer, sizeof(buffer), stdin)) {
  224. int len;
  225. char *cp;
  226. char *local_name;
  227. int single_force, not_for_merge;
  228. for (cp = buffer; *cp && !isspace(*cp); cp++)
  229. ;
  230. if (*cp)
  231. *cp++ = 0;
  232. len = strlen(cp);
  233. if (len && cp[len-1] == '\n')
  234. cp[--len] = 0;
  235. if (!strcmp(buffer, "failed"))
  236. die("Fetch failure: %s", remote);
  237. if (!strcmp(buffer, "pack"))
  238. continue;
  239. if (!strcmp(buffer, "keep")) {
  240. char *od = get_object_directory();
  241. int len = strlen(od) + strlen(cp) + 50;
  242. keep = xmalloc(len);
  243. sprintf(keep, "%s/pack/pack-%s.keep", od, cp);
  244. continue;
  245. }
  246. local_name = find_local_name(cp, refs,
  247. &single_force, &not_for_merge);
  248. if (!local_name)
  249. continue;
  250. err |= append_fetch_head(fp,
  251. buffer, remote, cp, remote_nick,
  252. local_name, not_for_merge,
  253. verbose, force || single_force);
  254. }
  255. return err;
  256. }
  257. static int parse_reflist(const char *reflist)
  258. {
  259. const char *ref;
  260. printf("refs='");
  261. for (ref = reflist; ref; ) {
  262. const char *next;
  263. while (*ref && isspace(*ref))
  264. ref++;
  265. if (!*ref)
  266. break;
  267. for (next = ref; *next && !isspace(*next); next++)
  268. ;
  269. printf("\n%.*s", (int)(next - ref), ref);
  270. ref = next;
  271. }
  272. printf("'\n");
  273. printf("rref='");
  274. for (ref = reflist; ref; ) {
  275. const char *next, *colon;
  276. while (*ref && isspace(*ref))
  277. ref++;
  278. if (!*ref)
  279. break;
  280. for (next = ref; *next && !isspace(*next); next++)
  281. ;
  282. if (*ref == '.')
  283. ref++;
  284. if (*ref == '+')
  285. ref++;
  286. colon = strchr(ref, ':');
  287. putchar('\n');
  288. printf("%.*s", (int)((colon ? colon : next) - ref), ref);
  289. ref = next;
  290. }
  291. printf("'\n");
  292. return 0;
  293. }
  294. static int expand_refs_wildcard(const char *ls_remote_result, int numrefs,
  295. const char **refs)
  296. {
  297. int i, matchlen, replacelen;
  298. int found_one = 0;
  299. const char *remote = *refs++;
  300. numrefs--;
  301. if (numrefs == 0) {
  302. fprintf(stderr, "Nothing specified for fetching with remote.%s.fetch\n",
  303. remote);
  304. printf("empty\n");
  305. }
  306. for (i = 0; i < numrefs; i++) {
  307. const char *ref = refs[i];
  308. const char *lref = ref;
  309. const char *colon;
  310. const char *tail;
  311. const char *ls;
  312. const char *next;
  313. if (*lref == '+')
  314. lref++;
  315. colon = strchr(lref, ':');
  316. tail = lref + strlen(lref);
  317. if (!(colon &&
  318. 2 < colon - lref &&
  319. colon[-1] == '*' &&
  320. colon[-2] == '/' &&
  321. 2 < tail - (colon + 1) &&
  322. tail[-1] == '*' &&
  323. tail[-2] == '/')) {
  324. /* not a glob */
  325. if (!found_one++)
  326. printf("explicit\n");
  327. printf("%s\n", ref);
  328. continue;
  329. }
  330. /* glob */
  331. if (!found_one++)
  332. printf("glob\n");
  333. /* lref to colon-2 is remote hierarchy name;
  334. * colon+1 to tail-2 is local.
  335. */
  336. matchlen = (colon-1) - lref;
  337. replacelen = (tail-1) - (colon+1);
  338. for (ls = ls_remote_result; ls; ls = next) {
  339. const char *eol;
  340. unsigned char sha1[20];
  341. int namelen;
  342. while (*ls && isspace(*ls))
  343. ls++;
  344. next = strchr(ls, '\n');
  345. eol = !next ? (ls + strlen(ls)) : next;
  346. if (!memcmp("^{}", eol-3, 3))
  347. continue;
  348. if (eol - ls < 40)
  349. continue;
  350. if (get_sha1_hex(ls, sha1))
  351. continue;
  352. ls += 40;
  353. while (ls < eol && isspace(*ls))
  354. ls++;
  355. /* ls to next (or eol) is the name.
  356. * is it identical to lref to colon-2?
  357. */
  358. if ((eol - ls) <= matchlen ||
  359. strncmp(ls, lref, matchlen))
  360. continue;
  361. /* Yes, it is a match */
  362. namelen = eol - ls;
  363. if (lref != ref)
  364. putchar('+');
  365. printf("%.*s:%.*s%.*s\n",
  366. namelen, ls,
  367. replacelen, colon + 1,
  368. namelen - matchlen, ls + matchlen);
  369. }
  370. }
  371. return 0;
  372. }
  373. static int pick_rref(int sha1_only, const char *rref, const char *ls_remote_result)
  374. {
  375. int err = 0;
  376. int lrr_count = lrr_count, i, pass;
  377. const char *cp;
  378. struct lrr {
  379. const char *line;
  380. const char *name;
  381. int namelen;
  382. int shown;
  383. } *lrr_list = lrr_list;
  384. for (pass = 0; pass < 2; pass++) {
  385. /* pass 0 counts and allocates, pass 1 fills... */
  386. cp = ls_remote_result;
  387. i = 0;
  388. while (1) {
  389. const char *np;
  390. while (*cp && isspace(*cp))
  391. cp++;
  392. if (!*cp)
  393. break;
  394. np = strchrnul(cp, '\n');
  395. if (pass) {
  396. lrr_list[i].line = cp;
  397. lrr_list[i].name = cp + 41;
  398. lrr_list[i].namelen = np - (cp + 41);
  399. }
  400. i++;
  401. cp = np;
  402. }
  403. if (!pass) {
  404. lrr_count = i;
  405. lrr_list = xcalloc(lrr_count, sizeof(*lrr_list));
  406. }
  407. }
  408. while (1) {
  409. const char *next;
  410. int rreflen;
  411. int i;
  412. while (*rref && isspace(*rref))
  413. rref++;
  414. if (!*rref)
  415. break;
  416. next = strchrnul(rref, '\n');
  417. rreflen = next - rref;
  418. for (i = 0; i < lrr_count; i++) {
  419. struct lrr *lrr = &(lrr_list[i]);
  420. if (rreflen == lrr->namelen &&
  421. !memcmp(lrr->name, rref, rreflen)) {
  422. if (!lrr->shown)
  423. printf("%.*s\n",
  424. sha1_only ? 40 : lrr->namelen + 41,
  425. lrr->line);
  426. lrr->shown = 1;
  427. break;
  428. }
  429. }
  430. if (lrr_count <= i) {
  431. error("pick-rref: %.*s not found", rreflen, rref);
  432. err = 1;
  433. }
  434. rref = next;
  435. }
  436. free(lrr_list);
  437. return err;
  438. }
  439. int cmd_fetch__tool(int argc, const char **argv, const char *prefix)
  440. {
  441. int verbose = 0;
  442. int force = 0;
  443. int sopt = 0;
  444. while (1 < argc) {
  445. const char *arg = argv[1];
  446. if (!strcmp("-v", arg))
  447. verbose = 1;
  448. else if (!strcmp("-f", arg))
  449. force = 1;
  450. else if (!strcmp("-s", arg))
  451. sopt = 1;
  452. else
  453. break;
  454. argc--;
  455. argv++;
  456. }
  457. if (argc <= 1)
  458. return error("Missing subcommand");
  459. if (!strcmp("append-fetch-head", argv[1])) {
  460. int result;
  461. FILE *fp;
  462. char *filename;
  463. if (argc != 8)
  464. return error("append-fetch-head takes 6 args");
  465. filename = git_path("FETCH_HEAD");
  466. fp = fopen(filename, "a");
  467. if (!fp)
  468. return error("cannot open %s: %s", filename, strerror(errno));
  469. result = append_fetch_head(fp, argv[2], argv[3],
  470. argv[4], argv[5],
  471. argv[6], !!argv[7][0],
  472. verbose, force);
  473. fclose(fp);
  474. return result;
  475. }
  476. if (!strcmp("native-store", argv[1])) {
  477. int result;
  478. FILE *fp;
  479. char *filename;
  480. if (argc != 5)
  481. return error("fetch-native-store takes 3 args");
  482. filename = git_path("FETCH_HEAD");
  483. fp = fopen(filename, "a");
  484. if (!fp)
  485. return error("cannot open %s: %s", filename, strerror(errno));
  486. result = fetch_native_store(fp, argv[2], argv[3], argv[4],
  487. verbose, force);
  488. fclose(fp);
  489. return result;
  490. }
  491. if (!strcmp("parse-reflist", argv[1])) {
  492. const char *reflist;
  493. if (argc != 3)
  494. return error("parse-reflist takes 1 arg");
  495. reflist = argv[2];
  496. if (!strcmp(reflist, "-"))
  497. reflist = get_stdin();
  498. return parse_reflist(reflist);
  499. }
  500. if (!strcmp("pick-rref", argv[1])) {
  501. const char *ls_remote_result;
  502. if (argc != 4)
  503. return error("pick-rref takes 2 args");
  504. ls_remote_result = argv[3];
  505. if (!strcmp(ls_remote_result, "-"))
  506. ls_remote_result = get_stdin();
  507. return pick_rref(sopt, argv[2], ls_remote_result);
  508. }
  509. if (!strcmp("expand-refs-wildcard", argv[1])) {
  510. const char *reflist;
  511. if (argc < 4)
  512. return error("expand-refs-wildcard takes at least 2 args");
  513. reflist = argv[2];
  514. if (!strcmp(reflist, "-"))
  515. reflist = get_stdin();
  516. return expand_refs_wildcard(reflist, argc - 3, argv + 3);
  517. }
  518. return error("Unknown subcommand: %s", argv[1]);
  519. }