THIS IS A TEST INSTANCE ONLY! REPOSITORIES CAN BE DELETED AT ANY TIME!

Git Source Code Mirror - This is a publish-only repository and all pull requests are ignored. Please follow Documentation/SubmittingPatches procedure for any of your improvements.
git
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

2488 lines
68KB

  1. #include "cache.h"
  2. #include "wt-status.h"
  3. #include "object.h"
  4. #include "dir.h"
  5. #include "commit.h"
  6. #include "diff.h"
  7. #include "revision.h"
  8. #include "diffcore.h"
  9. #include "quote.h"
  10. #include "run-command.h"
  11. #include "argv-array.h"
  12. #include "remote.h"
  13. #include "refs.h"
  14. #include "submodule.h"
  15. #include "column.h"
  16. #include "strbuf.h"
  17. #include "utf8.h"
  18. #include "worktree.h"
  19. #include "lockfile.h"
  20. #include "sequencer.h"
  21. #define AB_DELAY_WARNING_IN_MS (2 * 1000)
  22. static const char cut_line[] =
  23. "------------------------ >8 ------------------------\n";
  24. static char default_wt_status_colors[][COLOR_MAXLEN] = {
  25. GIT_COLOR_NORMAL, /* WT_STATUS_HEADER */
  26. GIT_COLOR_GREEN, /* WT_STATUS_UPDATED */
  27. GIT_COLOR_RED, /* WT_STATUS_CHANGED */
  28. GIT_COLOR_RED, /* WT_STATUS_UNTRACKED */
  29. GIT_COLOR_RED, /* WT_STATUS_NOBRANCH */
  30. GIT_COLOR_RED, /* WT_STATUS_UNMERGED */
  31. GIT_COLOR_GREEN, /* WT_STATUS_LOCAL_BRANCH */
  32. GIT_COLOR_RED, /* WT_STATUS_REMOTE_BRANCH */
  33. GIT_COLOR_NIL, /* WT_STATUS_ONBRANCH */
  34. };
  35. static const char *color(int slot, struct wt_status *s)
  36. {
  37. const char *c = "";
  38. if (want_color(s->use_color))
  39. c = s->color_palette[slot];
  40. if (slot == WT_STATUS_ONBRANCH && color_is_nil(c))
  41. c = s->color_palette[WT_STATUS_HEADER];
  42. return c;
  43. }
  44. static void status_vprintf(struct wt_status *s, int at_bol, const char *color,
  45. const char *fmt, va_list ap, const char *trail)
  46. {
  47. struct strbuf sb = STRBUF_INIT;
  48. struct strbuf linebuf = STRBUF_INIT;
  49. const char *line, *eol;
  50. strbuf_vaddf(&sb, fmt, ap);
  51. if (!sb.len) {
  52. if (s->display_comment_prefix) {
  53. strbuf_addch(&sb, comment_line_char);
  54. if (!trail)
  55. strbuf_addch(&sb, ' ');
  56. }
  57. color_print_strbuf(s->fp, color, &sb);
  58. if (trail)
  59. fprintf(s->fp, "%s", trail);
  60. strbuf_release(&sb);
  61. return;
  62. }
  63. for (line = sb.buf; *line; line = eol + 1) {
  64. eol = strchr(line, '\n');
  65. strbuf_reset(&linebuf);
  66. if (at_bol && s->display_comment_prefix) {
  67. strbuf_addch(&linebuf, comment_line_char);
  68. if (*line != '\n' && *line != '\t')
  69. strbuf_addch(&linebuf, ' ');
  70. }
  71. if (eol)
  72. strbuf_add(&linebuf, line, eol - line);
  73. else
  74. strbuf_addstr(&linebuf, line);
  75. color_print_strbuf(s->fp, color, &linebuf);
  76. if (eol)
  77. fprintf(s->fp, "\n");
  78. else
  79. break;
  80. at_bol = 1;
  81. }
  82. if (trail)
  83. fprintf(s->fp, "%s", trail);
  84. strbuf_release(&linebuf);
  85. strbuf_release(&sb);
  86. }
  87. void status_printf_ln(struct wt_status *s, const char *color,
  88. const char *fmt, ...)
  89. {
  90. va_list ap;
  91. va_start(ap, fmt);
  92. status_vprintf(s, 1, color, fmt, ap, "\n");
  93. va_end(ap);
  94. }
  95. void status_printf(struct wt_status *s, const char *color,
  96. const char *fmt, ...)
  97. {
  98. va_list ap;
  99. va_start(ap, fmt);
  100. status_vprintf(s, 1, color, fmt, ap, NULL);
  101. va_end(ap);
  102. }
  103. static void status_printf_more(struct wt_status *s, const char *color,
  104. const char *fmt, ...)
  105. {
  106. va_list ap;
  107. va_start(ap, fmt);
  108. status_vprintf(s, 0, color, fmt, ap, NULL);
  109. va_end(ap);
  110. }
  111. void wt_status_prepare(struct repository *r, struct wt_status *s)
  112. {
  113. memset(s, 0, sizeof(*s));
  114. s->repo = r;
  115. memcpy(s->color_palette, default_wt_status_colors,
  116. sizeof(default_wt_status_colors));
  117. s->show_untracked_files = SHOW_NORMAL_UNTRACKED_FILES;
  118. s->use_color = -1;
  119. s->relative_paths = 1;
  120. s->branch = resolve_refdup("HEAD", 0, NULL, NULL);
  121. s->reference = "HEAD";
  122. s->fp = stdout;
  123. s->index_file = get_index_file();
  124. s->change.strdup_strings = 1;
  125. s->untracked.strdup_strings = 1;
  126. s->ignored.strdup_strings = 1;
  127. s->show_branch = -1; /* unspecified */
  128. s->show_stash = 0;
  129. s->ahead_behind_flags = AHEAD_BEHIND_UNSPECIFIED;
  130. s->display_comment_prefix = 0;
  131. s->detect_rename = -1;
  132. s->rename_score = -1;
  133. s->rename_limit = -1;
  134. }
  135. static void wt_longstatus_print_unmerged_header(struct wt_status *s)
  136. {
  137. int i;
  138. int del_mod_conflict = 0;
  139. int both_deleted = 0;
  140. int not_deleted = 0;
  141. const char *c = color(WT_STATUS_HEADER, s);
  142. status_printf_ln(s, c, _("Unmerged paths:"));
  143. for (i = 0; i < s->change.nr; i++) {
  144. struct string_list_item *it = &(s->change.items[i]);
  145. struct wt_status_change_data *d = it->util;
  146. switch (d->stagemask) {
  147. case 0:
  148. break;
  149. case 1:
  150. both_deleted = 1;
  151. break;
  152. case 3:
  153. case 5:
  154. del_mod_conflict = 1;
  155. break;
  156. default:
  157. not_deleted = 1;
  158. break;
  159. }
  160. }
  161. if (!s->hints)
  162. return;
  163. if (s->whence != FROM_COMMIT)
  164. ;
  165. else if (!s->is_initial) {
  166. if (!strcmp(s->reference, "HEAD"))
  167. status_printf_ln(s, c,
  168. _(" (use \"git restore --staged <file>...\" to unstage)"));
  169. else
  170. status_printf_ln(s, c,
  171. _(" (use \"git restore --source=%s --staged <file>...\" to unstage)"),
  172. s->reference);
  173. } else
  174. status_printf_ln(s, c, _(" (use \"git rm --cached <file>...\" to unstage)"));
  175. if (!both_deleted) {
  176. if (!del_mod_conflict)
  177. status_printf_ln(s, c, _(" (use \"git add <file>...\" to mark resolution)"));
  178. else
  179. status_printf_ln(s, c, _(" (use \"git add/rm <file>...\" as appropriate to mark resolution)"));
  180. } else if (!del_mod_conflict && !not_deleted) {
  181. status_printf_ln(s, c, _(" (use \"git rm <file>...\" to mark resolution)"));
  182. } else {
  183. status_printf_ln(s, c, _(" (use \"git add/rm <file>...\" as appropriate to mark resolution)"));
  184. }
  185. }
  186. static void wt_longstatus_print_cached_header(struct wt_status *s)
  187. {
  188. const char *c = color(WT_STATUS_HEADER, s);
  189. status_printf_ln(s, c, _("Changes to be committed:"));
  190. if (!s->hints)
  191. return;
  192. if (s->whence != FROM_COMMIT)
  193. ; /* NEEDSWORK: use "git reset --unresolve"??? */
  194. else if (!s->is_initial) {
  195. if (!strcmp(s->reference, "HEAD"))
  196. status_printf_ln(s, c
  197. , _(" (use \"git restore --staged <file>...\" to unstage)"));
  198. else
  199. status_printf_ln(s, c,
  200. _(" (use \"git restore --source=%s --staged <file>...\" to unstage)"),
  201. s->reference);
  202. } else
  203. status_printf_ln(s, c, _(" (use \"git rm --cached <file>...\" to unstage)"));
  204. }
  205. static void wt_longstatus_print_dirty_header(struct wt_status *s,
  206. int has_deleted,
  207. int has_dirty_submodules)
  208. {
  209. const char *c = color(WT_STATUS_HEADER, s);
  210. status_printf_ln(s, c, _("Changes not staged for commit:"));
  211. if (!s->hints)
  212. return;
  213. if (!has_deleted)
  214. status_printf_ln(s, c, _(" (use \"git add <file>...\" to update what will be committed)"));
  215. else
  216. status_printf_ln(s, c, _(" (use \"git add/rm <file>...\" to update what will be committed)"));
  217. status_printf_ln(s, c, _(" (use \"git restore <file>...\" to discard changes in working directory)"));
  218. if (has_dirty_submodules)
  219. status_printf_ln(s, c, _(" (commit or discard the untracked or modified content in submodules)"));
  220. }
  221. static void wt_longstatus_print_other_header(struct wt_status *s,
  222. const char *what,
  223. const char *how)
  224. {
  225. const char *c = color(WT_STATUS_HEADER, s);
  226. status_printf_ln(s, c, "%s:", what);
  227. if (!s->hints)
  228. return;
  229. status_printf_ln(s, c, _(" (use \"git %s <file>...\" to include in what will be committed)"), how);
  230. }
  231. static void wt_longstatus_print_trailer(struct wt_status *s)
  232. {
  233. status_printf_ln(s, color(WT_STATUS_HEADER, s), "%s", "");
  234. }
  235. #define quote_path quote_path_relative
  236. static const char *wt_status_unmerged_status_string(int stagemask)
  237. {
  238. switch (stagemask) {
  239. case 1:
  240. return _("both deleted:");
  241. case 2:
  242. return _("added by us:");
  243. case 3:
  244. return _("deleted by them:");
  245. case 4:
  246. return _("added by them:");
  247. case 5:
  248. return _("deleted by us:");
  249. case 6:
  250. return _("both added:");
  251. case 7:
  252. return _("both modified:");
  253. default:
  254. BUG("unhandled unmerged status %x", stagemask);
  255. }
  256. }
  257. static const char *wt_status_diff_status_string(int status)
  258. {
  259. switch (status) {
  260. case DIFF_STATUS_ADDED:
  261. return _("new file:");
  262. case DIFF_STATUS_COPIED:
  263. return _("copied:");
  264. case DIFF_STATUS_DELETED:
  265. return _("deleted:");
  266. case DIFF_STATUS_MODIFIED:
  267. return _("modified:");
  268. case DIFF_STATUS_RENAMED:
  269. return _("renamed:");
  270. case DIFF_STATUS_TYPE_CHANGED:
  271. return _("typechange:");
  272. case DIFF_STATUS_UNKNOWN:
  273. return _("unknown:");
  274. case DIFF_STATUS_UNMERGED:
  275. return _("unmerged:");
  276. default:
  277. return NULL;
  278. }
  279. }
  280. static int maxwidth(const char *(*label)(int), int minval, int maxval)
  281. {
  282. int result = 0, i;
  283. for (i = minval; i <= maxval; i++) {
  284. const char *s = label(i);
  285. int len = s ? utf8_strwidth(s) : 0;
  286. if (len > result)
  287. result = len;
  288. }
  289. return result;
  290. }
  291. static void wt_longstatus_print_unmerged_data(struct wt_status *s,
  292. struct string_list_item *it)
  293. {
  294. const char *c = color(WT_STATUS_UNMERGED, s);
  295. struct wt_status_change_data *d = it->util;
  296. struct strbuf onebuf = STRBUF_INIT;
  297. static char *padding;
  298. static int label_width;
  299. const char *one, *how;
  300. int len;
  301. if (!padding) {
  302. label_width = maxwidth(wt_status_unmerged_status_string, 1, 7);
  303. label_width += strlen(" ");
  304. padding = xmallocz(label_width);
  305. memset(padding, ' ', label_width);
  306. }
  307. one = quote_path(it->string, s->prefix, &onebuf);
  308. status_printf(s, color(WT_STATUS_HEADER, s), "\t");
  309. how = wt_status_unmerged_status_string(d->stagemask);
  310. len = label_width - utf8_strwidth(how);
  311. status_printf_more(s, c, "%s%.*s%s\n", how, len, padding, one);
  312. strbuf_release(&onebuf);
  313. }
  314. static void wt_longstatus_print_change_data(struct wt_status *s,
  315. int change_type,
  316. struct string_list_item *it)
  317. {
  318. struct wt_status_change_data *d = it->util;
  319. const char *c = color(change_type, s);
  320. int status;
  321. char *one_name;
  322. char *two_name;
  323. const char *one, *two;
  324. struct strbuf onebuf = STRBUF_INIT, twobuf = STRBUF_INIT;
  325. struct strbuf extra = STRBUF_INIT;
  326. static char *padding;
  327. static int label_width;
  328. const char *what;
  329. int len;
  330. if (!padding) {
  331. /* If DIFF_STATUS_* uses outside the range [A..Z], we're in trouble */
  332. label_width = maxwidth(wt_status_diff_status_string, 'A', 'Z');
  333. label_width += strlen(" ");
  334. padding = xmallocz(label_width);
  335. memset(padding, ' ', label_width);
  336. }
  337. one_name = two_name = it->string;
  338. switch (change_type) {
  339. case WT_STATUS_UPDATED:
  340. status = d->index_status;
  341. break;
  342. case WT_STATUS_CHANGED:
  343. if (d->new_submodule_commits || d->dirty_submodule) {
  344. strbuf_addstr(&extra, " (");
  345. if (d->new_submodule_commits)
  346. strbuf_addstr(&extra, _("new commits, "));
  347. if (d->dirty_submodule & DIRTY_SUBMODULE_MODIFIED)
  348. strbuf_addstr(&extra, _("modified content, "));
  349. if (d->dirty_submodule & DIRTY_SUBMODULE_UNTRACKED)
  350. strbuf_addstr(&extra, _("untracked content, "));
  351. strbuf_setlen(&extra, extra.len - 2);
  352. strbuf_addch(&extra, ')');
  353. }
  354. status = d->worktree_status;
  355. break;
  356. default:
  357. BUG("unhandled change_type %d in wt_longstatus_print_change_data",
  358. change_type);
  359. }
  360. /*
  361. * Only pick up the rename it's relevant. If the rename is for
  362. * the changed section and we're printing the updated section,
  363. * ignore it.
  364. */
  365. if (d->rename_status == status)
  366. one_name = d->rename_source;
  367. one = quote_path(one_name, s->prefix, &onebuf);
  368. two = quote_path(two_name, s->prefix, &twobuf);
  369. status_printf(s, color(WT_STATUS_HEADER, s), "\t");
  370. what = wt_status_diff_status_string(status);
  371. if (!what)
  372. BUG("unhandled diff status %c", status);
  373. len = label_width - utf8_strwidth(what);
  374. assert(len >= 0);
  375. if (one_name != two_name)
  376. status_printf_more(s, c, "%s%.*s%s -> %s",
  377. what, len, padding, one, two);
  378. else
  379. status_printf_more(s, c, "%s%.*s%s",
  380. what, len, padding, one);
  381. if (extra.len) {
  382. status_printf_more(s, color(WT_STATUS_HEADER, s), "%s", extra.buf);
  383. strbuf_release(&extra);
  384. }
  385. status_printf_more(s, GIT_COLOR_NORMAL, "\n");
  386. strbuf_release(&onebuf);
  387. strbuf_release(&twobuf);
  388. }
  389. static char short_submodule_status(struct wt_status_change_data *d)
  390. {
  391. if (d->new_submodule_commits)
  392. return 'M';
  393. if (d->dirty_submodule & DIRTY_SUBMODULE_MODIFIED)
  394. return 'm';
  395. if (d->dirty_submodule & DIRTY_SUBMODULE_UNTRACKED)
  396. return '?';
  397. return d->worktree_status;
  398. }
  399. static void wt_status_collect_changed_cb(struct diff_queue_struct *q,
  400. struct diff_options *options,
  401. void *data)
  402. {
  403. struct wt_status *s = data;
  404. int i;
  405. if (!q->nr)
  406. return;
  407. s->workdir_dirty = 1;
  408. for (i = 0; i < q->nr; i++) {
  409. struct diff_filepair *p;
  410. struct string_list_item *it;
  411. struct wt_status_change_data *d;
  412. p = q->queue[i];
  413. it = string_list_insert(&s->change, p->two->path);
  414. d = it->util;
  415. if (!d) {
  416. d = xcalloc(1, sizeof(*d));
  417. it->util = d;
  418. }
  419. if (!d->worktree_status)
  420. d->worktree_status = p->status;
  421. if (S_ISGITLINK(p->two->mode)) {
  422. d->dirty_submodule = p->two->dirty_submodule;
  423. d->new_submodule_commits = !oideq(&p->one->oid,
  424. &p->two->oid);
  425. if (s->status_format == STATUS_FORMAT_SHORT)
  426. d->worktree_status = short_submodule_status(d);
  427. }
  428. switch (p->status) {
  429. case DIFF_STATUS_ADDED:
  430. d->mode_worktree = p->two->mode;
  431. break;
  432. case DIFF_STATUS_DELETED:
  433. d->mode_index = p->one->mode;
  434. oidcpy(&d->oid_index, &p->one->oid);
  435. /* mode_worktree is zero for a delete. */
  436. break;
  437. case DIFF_STATUS_COPIED:
  438. case DIFF_STATUS_RENAMED:
  439. if (d->rename_status)
  440. BUG("multiple renames on the same target? how?");
  441. d->rename_source = xstrdup(p->one->path);
  442. d->rename_score = p->score * 100 / MAX_SCORE;
  443. d->rename_status = p->status;
  444. /* fallthru */
  445. case DIFF_STATUS_MODIFIED:
  446. case DIFF_STATUS_TYPE_CHANGED:
  447. case DIFF_STATUS_UNMERGED:
  448. d->mode_index = p->one->mode;
  449. d->mode_worktree = p->two->mode;
  450. oidcpy(&d->oid_index, &p->one->oid);
  451. break;
  452. default:
  453. BUG("unhandled diff-files status '%c'", p->status);
  454. break;
  455. }
  456. }
  457. }
  458. static int unmerged_mask(struct index_state *istate, const char *path)
  459. {
  460. int pos, mask;
  461. const struct cache_entry *ce;
  462. pos = index_name_pos(istate, path, strlen(path));
  463. if (0 <= pos)
  464. return 0;
  465. mask = 0;
  466. pos = -pos-1;
  467. while (pos < istate->cache_nr) {
  468. ce = istate->cache[pos++];
  469. if (strcmp(ce->name, path) || !ce_stage(ce))
  470. break;
  471. mask |= (1 << (ce_stage(ce) - 1));
  472. }
  473. return mask;
  474. }
  475. static void wt_status_collect_updated_cb(struct diff_queue_struct *q,
  476. struct diff_options *options,
  477. void *data)
  478. {
  479. struct wt_status *s = data;
  480. int i;
  481. for (i = 0; i < q->nr; i++) {
  482. struct diff_filepair *p;
  483. struct string_list_item *it;
  484. struct wt_status_change_data *d;
  485. p = q->queue[i];
  486. it = string_list_insert(&s->change, p->two->path);
  487. d = it->util;
  488. if (!d) {
  489. d = xcalloc(1, sizeof(*d));
  490. it->util = d;
  491. }
  492. if (!d->index_status)
  493. d->index_status = p->status;
  494. switch (p->status) {
  495. case DIFF_STATUS_ADDED:
  496. /* Leave {mode,oid}_head zero for an add. */
  497. d->mode_index = p->two->mode;
  498. oidcpy(&d->oid_index, &p->two->oid);
  499. s->committable = 1;
  500. break;
  501. case DIFF_STATUS_DELETED:
  502. d->mode_head = p->one->mode;
  503. oidcpy(&d->oid_head, &p->one->oid);
  504. s->committable = 1;
  505. /* Leave {mode,oid}_index zero for a delete. */
  506. break;
  507. case DIFF_STATUS_COPIED:
  508. case DIFF_STATUS_RENAMED:
  509. if (d->rename_status)
  510. BUG("multiple renames on the same target? how?");
  511. d->rename_source = xstrdup(p->one->path);
  512. d->rename_score = p->score * 100 / MAX_SCORE;
  513. d->rename_status = p->status;
  514. /* fallthru */
  515. case DIFF_STATUS_MODIFIED:
  516. case DIFF_STATUS_TYPE_CHANGED:
  517. d->mode_head = p->one->mode;
  518. d->mode_index = p->two->mode;
  519. oidcpy(&d->oid_head, &p->one->oid);
  520. oidcpy(&d->oid_index, &p->two->oid);
  521. s->committable = 1;
  522. break;
  523. case DIFF_STATUS_UNMERGED:
  524. d->stagemask = unmerged_mask(s->repo->index,
  525. p->two->path);
  526. /*
  527. * Don't bother setting {mode,oid}_{head,index} since the print
  528. * code will output the stage values directly and not use the
  529. * values in these fields.
  530. */
  531. break;
  532. default:
  533. BUG("unhandled diff-index status '%c'", p->status);
  534. break;
  535. }
  536. }
  537. }
  538. static void wt_status_collect_changes_worktree(struct wt_status *s)
  539. {
  540. struct rev_info rev;
  541. repo_init_revisions(s->repo, &rev, NULL);
  542. setup_revisions(0, NULL, &rev, NULL);
  543. rev.diffopt.output_format |= DIFF_FORMAT_CALLBACK;
  544. rev.diffopt.flags.dirty_submodules = 1;
  545. rev.diffopt.ita_invisible_in_index = 1;
  546. if (!s->show_untracked_files)
  547. rev.diffopt.flags.ignore_untracked_in_submodules = 1;
  548. if (s->ignore_submodule_arg) {
  549. rev.diffopt.flags.override_submodule_config = 1;
  550. handle_ignore_submodules_arg(&rev.diffopt, s->ignore_submodule_arg);
  551. }
  552. rev.diffopt.format_callback = wt_status_collect_changed_cb;
  553. rev.diffopt.format_callback_data = s;
  554. rev.diffopt.detect_rename = s->detect_rename >= 0 ? s->detect_rename : rev.diffopt.detect_rename;
  555. rev.diffopt.rename_limit = s->rename_limit >= 0 ? s->rename_limit : rev.diffopt.rename_limit;
  556. rev.diffopt.rename_score = s->rename_score >= 0 ? s->rename_score : rev.diffopt.rename_score;
  557. copy_pathspec(&rev.prune_data, &s->pathspec);
  558. run_diff_files(&rev, 0);
  559. }
  560. static void wt_status_collect_changes_index(struct wt_status *s)
  561. {
  562. struct rev_info rev;
  563. struct setup_revision_opt opt;
  564. repo_init_revisions(s->repo, &rev, NULL);
  565. memset(&opt, 0, sizeof(opt));
  566. opt.def = s->is_initial ? empty_tree_oid_hex() : s->reference;
  567. setup_revisions(0, NULL, &rev, &opt);
  568. rev.diffopt.flags.override_submodule_config = 1;
  569. rev.diffopt.ita_invisible_in_index = 1;
  570. if (s->ignore_submodule_arg) {
  571. handle_ignore_submodules_arg(&rev.diffopt, s->ignore_submodule_arg);
  572. } else {
  573. /*
  574. * Unless the user did explicitly request a submodule ignore
  575. * mode by passing a command line option we do not ignore any
  576. * changed submodule SHA-1s when comparing index and HEAD, no
  577. * matter what is configured. Otherwise the user won't be
  578. * shown any submodules she manually added (and which are
  579. * staged to be committed), which would be really confusing.
  580. */
  581. handle_ignore_submodules_arg(&rev.diffopt, "dirty");
  582. }
  583. rev.diffopt.output_format |= DIFF_FORMAT_CALLBACK;
  584. rev.diffopt.format_callback = wt_status_collect_updated_cb;
  585. rev.diffopt.format_callback_data = s;
  586. rev.diffopt.detect_rename = s->detect_rename >= 0 ? s->detect_rename : rev.diffopt.detect_rename;
  587. rev.diffopt.rename_limit = s->rename_limit >= 0 ? s->rename_limit : rev.diffopt.rename_limit;
  588. rev.diffopt.rename_score = s->rename_score >= 0 ? s->rename_score : rev.diffopt.rename_score;
  589. copy_pathspec(&rev.prune_data, &s->pathspec);
  590. run_diff_index(&rev, 1);
  591. }
  592. static void wt_status_collect_changes_initial(struct wt_status *s)
  593. {
  594. struct index_state *istate = s->repo->index;
  595. int i;
  596. for (i = 0; i < istate->cache_nr; i++) {
  597. struct string_list_item *it;
  598. struct wt_status_change_data *d;
  599. const struct cache_entry *ce = istate->cache[i];
  600. if (!ce_path_match(istate, ce, &s->pathspec, NULL))
  601. continue;
  602. if (ce_intent_to_add(ce))
  603. continue;
  604. it = string_list_insert(&s->change, ce->name);
  605. d = it->util;
  606. if (!d) {
  607. d = xcalloc(1, sizeof(*d));
  608. it->util = d;
  609. }
  610. if (ce_stage(ce)) {
  611. d->index_status = DIFF_STATUS_UNMERGED;
  612. d->stagemask |= (1 << (ce_stage(ce) - 1));
  613. /*
  614. * Don't bother setting {mode,oid}_{head,index} since the print
  615. * code will output the stage values directly and not use the
  616. * values in these fields.
  617. */
  618. s->committable = 1;
  619. } else {
  620. d->index_status = DIFF_STATUS_ADDED;
  621. /* Leave {mode,oid}_head zero for adds. */
  622. d->mode_index = ce->ce_mode;
  623. oidcpy(&d->oid_index, &ce->oid);
  624. s->committable = 1;
  625. }
  626. }
  627. }
  628. static void wt_status_collect_untracked(struct wt_status *s)
  629. {
  630. int i;
  631. struct dir_struct dir;
  632. uint64_t t_begin = getnanotime();
  633. struct index_state *istate = s->repo->index;
  634. if (!s->show_untracked_files)
  635. return;
  636. memset(&dir, 0, sizeof(dir));
  637. if (s->show_untracked_files != SHOW_ALL_UNTRACKED_FILES)
  638. dir.flags |=
  639. DIR_SHOW_OTHER_DIRECTORIES | DIR_HIDE_EMPTY_DIRECTORIES;
  640. if (s->show_ignored_mode) {
  641. dir.flags |= DIR_SHOW_IGNORED_TOO;
  642. if (s->show_ignored_mode == SHOW_MATCHING_IGNORED)
  643. dir.flags |= DIR_SHOW_IGNORED_TOO_MODE_MATCHING;
  644. } else {
  645. dir.untracked = istate->untracked;
  646. }
  647. setup_standard_excludes(&dir);
  648. fill_directory(&dir, istate, &s->pathspec);
  649. for (i = 0; i < dir.nr; i++) {
  650. struct dir_entry *ent = dir.entries[i];
  651. if (index_name_is_other(istate, ent->name, ent->len) &&
  652. dir_path_match(istate, ent, &s->pathspec, 0, NULL))
  653. string_list_insert(&s->untracked, ent->name);
  654. free(ent);
  655. }
  656. for (i = 0; i < dir.ignored_nr; i++) {
  657. struct dir_entry *ent = dir.ignored[i];
  658. if (index_name_is_other(istate, ent->name, ent->len) &&
  659. dir_path_match(istate, ent, &s->pathspec, 0, NULL))
  660. string_list_insert(&s->ignored, ent->name);
  661. free(ent);
  662. }
  663. free(dir.entries);
  664. free(dir.ignored);
  665. clear_directory(&dir);
  666. if (advice_status_u_option)
  667. s->untracked_in_ms = (getnanotime() - t_begin) / 1000000;
  668. }
  669. static int has_unmerged(struct wt_status *s)
  670. {
  671. int i;
  672. for (i = 0; i < s->change.nr; i++) {
  673. struct wt_status_change_data *d;
  674. d = s->change.items[i].util;
  675. if (d->stagemask)
  676. return 1;
  677. }
  678. return 0;
  679. }
  680. void wt_status_collect(struct wt_status *s)
  681. {
  682. trace2_region_enter("status", "worktrees", s->repo);
  683. wt_status_collect_changes_worktree(s);
  684. trace2_region_leave("status", "worktrees", s->repo);
  685. if (s->is_initial) {
  686. trace2_region_enter("status", "initial", s->repo);
  687. wt_status_collect_changes_initial(s);
  688. trace2_region_leave("status", "initial", s->repo);
  689. } else {
  690. trace2_region_enter("status", "index", s->repo);
  691. wt_status_collect_changes_index(s);
  692. trace2_region_leave("status", "index", s->repo);
  693. }
  694. trace2_region_enter("status", "untracked", s->repo);
  695. wt_status_collect_untracked(s);
  696. trace2_region_leave("status", "untracked", s->repo);
  697. wt_status_get_state(s->repo, &s->state, s->branch && !strcmp(s->branch, "HEAD"));
  698. if (s->state.merge_in_progress && !has_unmerged(s))
  699. s->committable = 1;
  700. }
  701. void wt_status_collect_free_buffers(struct wt_status *s)
  702. {
  703. free(s->state.branch);
  704. free(s->state.onto);
  705. free(s->state.detached_from);
  706. }
  707. static void wt_longstatus_print_unmerged(struct wt_status *s)
  708. {
  709. int shown_header = 0;
  710. int i;
  711. for (i = 0; i < s->change.nr; i++) {
  712. struct wt_status_change_data *d;
  713. struct string_list_item *it;
  714. it = &(s->change.items[i]);
  715. d = it->util;
  716. if (!d->stagemask)
  717. continue;
  718. if (!shown_header) {
  719. wt_longstatus_print_unmerged_header(s);
  720. shown_header = 1;
  721. }
  722. wt_longstatus_print_unmerged_data(s, it);
  723. }
  724. if (shown_header)
  725. wt_longstatus_print_trailer(s);
  726. }
  727. static void wt_longstatus_print_updated(struct wt_status *s)
  728. {
  729. int shown_header = 0;
  730. int i;
  731. for (i = 0; i < s->change.nr; i++) {
  732. struct wt_status_change_data *d;
  733. struct string_list_item *it;
  734. it = &(s->change.items[i]);
  735. d = it->util;
  736. if (!d->index_status ||
  737. d->index_status == DIFF_STATUS_UNMERGED)
  738. continue;
  739. if (!shown_header) {
  740. wt_longstatus_print_cached_header(s);
  741. shown_header = 1;
  742. }
  743. wt_longstatus_print_change_data(s, WT_STATUS_UPDATED, it);
  744. }
  745. if (shown_header)
  746. wt_longstatus_print_trailer(s);
  747. }
  748. /*
  749. * -1 : has delete
  750. * 0 : no change
  751. * 1 : some change but no delete
  752. */
  753. static int wt_status_check_worktree_changes(struct wt_status *s,
  754. int *dirty_submodules)
  755. {
  756. int i;
  757. int changes = 0;
  758. *dirty_submodules = 0;
  759. for (i = 0; i < s->change.nr; i++) {
  760. struct wt_status_change_data *d;
  761. d = s->change.items[i].util;
  762. if (!d->worktree_status ||
  763. d->worktree_status == DIFF_STATUS_UNMERGED)
  764. continue;
  765. if (!changes)
  766. changes = 1;
  767. if (d->dirty_submodule)
  768. *dirty_submodules = 1;
  769. if (d->worktree_status == DIFF_STATUS_DELETED)
  770. changes = -1;
  771. }
  772. return changes;
  773. }
  774. static void wt_longstatus_print_changed(struct wt_status *s)
  775. {
  776. int i, dirty_submodules;
  777. int worktree_changes = wt_status_check_worktree_changes(s, &dirty_submodules);
  778. if (!worktree_changes)
  779. return;
  780. wt_longstatus_print_dirty_header(s, worktree_changes < 0, dirty_submodules);
  781. for (i = 0; i < s->change.nr; i++) {
  782. struct wt_status_change_data *d;
  783. struct string_list_item *it;
  784. it = &(s->change.items[i]);
  785. d = it->util;
  786. if (!d->worktree_status ||
  787. d->worktree_status == DIFF_STATUS_UNMERGED)
  788. continue;
  789. wt_longstatus_print_change_data(s, WT_STATUS_CHANGED, it);
  790. }
  791. wt_longstatus_print_trailer(s);
  792. }
  793. static int stash_count_refs(struct object_id *ooid, struct object_id *noid,
  794. const char *email, timestamp_t timestamp, int tz,
  795. const char *message, void *cb_data)
  796. {
  797. int *c = cb_data;
  798. (*c)++;
  799. return 0;
  800. }
  801. static void wt_longstatus_print_stash_summary(struct wt_status *s)
  802. {
  803. int stash_count = 0;
  804. for_each_reflog_ent("refs/stash", stash_count_refs, &stash_count);
  805. if (stash_count > 0)
  806. status_printf_ln(s, GIT_COLOR_NORMAL,
  807. Q_("Your stash currently has %d entry",
  808. "Your stash currently has %d entries", stash_count),
  809. stash_count);
  810. }
  811. static void wt_longstatus_print_submodule_summary(struct wt_status *s, int uncommitted)
  812. {
  813. struct child_process sm_summary = CHILD_PROCESS_INIT;
  814. struct strbuf cmd_stdout = STRBUF_INIT;
  815. struct strbuf summary = STRBUF_INIT;
  816. char *summary_content;
  817. argv_array_pushf(&sm_summary.env_array, "GIT_INDEX_FILE=%s",
  818. s->index_file);
  819. argv_array_push(&sm_summary.args, "submodule");
  820. argv_array_push(&sm_summary.args, "summary");
  821. argv_array_push(&sm_summary.args, uncommitted ? "--files" : "--cached");
  822. argv_array_push(&sm_summary.args, "--for-status");
  823. argv_array_push(&sm_summary.args, "--summary-limit");
  824. argv_array_pushf(&sm_summary.args, "%d", s->submodule_summary);
  825. if (!uncommitted)
  826. argv_array_push(&sm_summary.args, s->amend ? "HEAD^" : "HEAD");
  827. sm_summary.git_cmd = 1;
  828. sm_summary.no_stdin = 1;
  829. capture_command(&sm_summary, &cmd_stdout, 1024);
  830. /* prepend header, only if there's an actual output */
  831. if (cmd_stdout.len) {
  832. if (uncommitted)
  833. strbuf_addstr(&summary, _("Submodules changed but not updated:"));
  834. else
  835. strbuf_addstr(&summary, _("Submodule changes to be committed:"));
  836. strbuf_addstr(&summary, "\n\n");
  837. }
  838. strbuf_addbuf(&summary, &cmd_stdout);
  839. strbuf_release(&cmd_stdout);
  840. if (s->display_comment_prefix) {
  841. size_t len;
  842. summary_content = strbuf_detach(&summary, &len);
  843. strbuf_add_commented_lines(&summary, summary_content, len);
  844. free(summary_content);
  845. }
  846. fputs(summary.buf, s->fp);
  847. strbuf_release(&summary);
  848. }
  849. static void wt_longstatus_print_other(struct wt_status *s,
  850. struct string_list *l,
  851. const char *what,
  852. const char *how)
  853. {
  854. int i;
  855. struct strbuf buf = STRBUF_INIT;
  856. static struct string_list output = STRING_LIST_INIT_DUP;
  857. struct column_options copts;
  858. if (!l->nr)
  859. return;
  860. wt_longstatus_print_other_header(s, what, how);
  861. for (i = 0; i < l->nr; i++) {
  862. struct string_list_item *it;
  863. const char *path;
  864. it = &(l->items[i]);
  865. path = quote_path(it->string, s->prefix, &buf);
  866. if (column_active(s->colopts)) {
  867. string_list_append(&output, path);
  868. continue;
  869. }
  870. status_printf(s, color(WT_STATUS_HEADER, s), "\t");
  871. status_printf_more(s, color(WT_STATUS_UNTRACKED, s),
  872. "%s\n", path);
  873. }
  874. strbuf_release(&buf);
  875. if (!column_active(s->colopts))
  876. goto conclude;
  877. strbuf_addf(&buf, "%s%s\t%s",
  878. color(WT_STATUS_HEADER, s),
  879. s->display_comment_prefix ? "#" : "",
  880. color(WT_STATUS_UNTRACKED, s));
  881. memset(&copts, 0, sizeof(copts));
  882. copts.padding = 1;
  883. copts.indent = buf.buf;
  884. if (want_color(s->use_color))
  885. copts.nl = GIT_COLOR_RESET "\n";
  886. print_columns(&output, s->colopts, &copts);
  887. string_list_clear(&output, 0);
  888. strbuf_release(&buf);
  889. conclude:
  890. status_printf_ln(s, GIT_COLOR_NORMAL, "%s", "");
  891. }
  892. size_t wt_status_locate_end(const char *s, size_t len)
  893. {
  894. const char *p;
  895. struct strbuf pattern = STRBUF_INIT;
  896. strbuf_addf(&pattern, "\n%c %s", comment_line_char, cut_line);
  897. if (starts_with(s, pattern.buf + 1))
  898. len = 0;
  899. else if ((p = strstr(s, pattern.buf)))
  900. len = p - s + 1;
  901. strbuf_release(&pattern);
  902. return len;
  903. }
  904. void wt_status_append_cut_line(struct strbuf *buf)
  905. {
  906. const char *explanation = _("Do not modify or remove the line above.\nEverything below it will be ignored.");
  907. strbuf_commented_addf(buf, "%s", cut_line);
  908. strbuf_add_commented_lines(buf, explanation, strlen(explanation));
  909. }
  910. void wt_status_add_cut_line(FILE *fp)
  911. {
  912. struct strbuf buf = STRBUF_INIT;
  913. wt_status_append_cut_line(&buf);
  914. fputs(buf.buf, fp);
  915. strbuf_release(&buf);
  916. }
  917. static void wt_longstatus_print_verbose(struct wt_status *s)
  918. {
  919. struct rev_info rev;
  920. struct setup_revision_opt opt;
  921. int dirty_submodules;
  922. const char *c = color(WT_STATUS_HEADER, s);
  923. repo_init_revisions(s->repo, &rev, NULL);
  924. rev.diffopt.flags.allow_textconv = 1;
  925. rev.diffopt.ita_invisible_in_index = 1;
  926. memset(&opt, 0, sizeof(opt));
  927. opt.def = s->is_initial ? empty_tree_oid_hex() : s->reference;
  928. setup_revisions(0, NULL, &rev, &opt);
  929. rev.diffopt.output_format |= DIFF_FORMAT_PATCH;
  930. rev.diffopt.detect_rename = s->detect_rename >= 0 ? s->detect_rename : rev.diffopt.detect_rename;
  931. rev.diffopt.rename_limit = s->rename_limit >= 0 ? s->rename_limit : rev.diffopt.rename_limit;
  932. rev.diffopt.rename_score = s->rename_score >= 0 ? s->rename_score : rev.diffopt.rename_score;
  933. rev.diffopt.file = s->fp;
  934. rev.diffopt.close_file = 0;
  935. /*
  936. * If we're not going to stdout, then we definitely don't
  937. * want color, since we are going to the commit message
  938. * file (and even the "auto" setting won't work, since it
  939. * will have checked isatty on stdout). But we then do want
  940. * to insert the scissor line here to reliably remove the
  941. * diff before committing.
  942. */
  943. if (s->fp != stdout) {
  944. rev.diffopt.use_color = 0;
  945. wt_status_add_cut_line(s->fp);
  946. }
  947. if (s->verbose > 1 && s->committable) {
  948. /* print_updated() printed a header, so do we */
  949. if (s->fp != stdout)
  950. wt_longstatus_print_trailer(s);
  951. status_printf_ln(s, c, _("Changes to be committed:"));
  952. rev.diffopt.a_prefix = "c/";
  953. rev.diffopt.b_prefix = "i/";
  954. } /* else use prefix as per user config */
  955. run_diff_index(&rev, 1);
  956. if (s->verbose > 1 &&
  957. wt_status_check_worktree_changes(s, &dirty_submodules)) {
  958. status_printf_ln(s, c,
  959. "--------------------------------------------------");
  960. status_printf_ln(s, c, _("Changes not staged for commit:"));
  961. setup_work_tree();
  962. rev.diffopt.a_prefix = "i/";
  963. rev.diffopt.b_prefix = "w/";
  964. run_diff_files(&rev, 0);
  965. }
  966. }
  967. static void wt_longstatus_print_tracking(struct wt_status *s)
  968. {
  969. struct strbuf sb = STRBUF_INIT;
  970. const char *cp, *ep, *branch_name;
  971. struct branch *branch;
  972. char comment_line_string[3];
  973. int i;
  974. uint64_t t_begin = 0;
  975. assert(s->branch && !s->is_initial);
  976. if (!skip_prefix(s->branch, "refs/heads/", &branch_name))
  977. return;
  978. branch = branch_get(branch_name);
  979. t_begin = getnanotime();
  980. if (!format_tracking_info(branch, &sb, s->ahead_behind_flags))
  981. return;
  982. if (advice_status_ahead_behind_warning &&
  983. s->ahead_behind_flags == AHEAD_BEHIND_FULL) {
  984. uint64_t t_delta_in_ms = (getnanotime() - t_begin) / 1000000;
  985. if (t_delta_in_ms > AB_DELAY_WARNING_IN_MS) {
  986. strbuf_addf(&sb, _("\n"
  987. "It took %.2f seconds to compute the branch ahead/behind values.\n"
  988. "You can use '--no-ahead-behind' to avoid this.\n"),
  989. t_delta_in_ms / 1000.0);
  990. }
  991. }
  992. i = 0;
  993. if (s->display_comment_prefix) {
  994. comment_line_string[i++] = comment_line_char;
  995. comment_line_string[i++] = ' ';
  996. }
  997. comment_line_string[i] = '\0';
  998. for (cp = sb.buf; (ep = strchr(cp, '\n')) != NULL; cp = ep + 1)
  999. color_fprintf_ln(s->fp, color(WT_STATUS_HEADER, s),
  1000. "%s%.*s", comment_line_string,
  1001. (int)(ep - cp), cp);
  1002. if (s->display_comment_prefix)
  1003. color_fprintf_ln(s->fp, color(WT_STATUS_HEADER, s), "%c",
  1004. comment_line_char);
  1005. else
  1006. fputs("\n", s->fp);
  1007. strbuf_release(&sb);
  1008. }
  1009. static void show_merge_in_progress(struct wt_status *s,
  1010. const char *color)
  1011. {
  1012. if (has_unmerged(s)) {
  1013. status_printf_ln(s, color, _("You have unmerged paths."));
  1014. if (s->hints) {
  1015. status_printf_ln(s, color,
  1016. _(" (fix conflicts and run \"git commit\")"));
  1017. status_printf_ln(s, color,
  1018. _(" (use \"git merge --abort\" to abort the merge)"));
  1019. }
  1020. } else {
  1021. status_printf_ln(s, color,
  1022. _("All conflicts fixed but you are still merging."));
  1023. if (s->hints)
  1024. status_printf_ln(s, color,
  1025. _(" (use \"git commit\" to conclude merge)"));
  1026. }
  1027. wt_longstatus_print_trailer(s);
  1028. }
  1029. static void show_am_in_progress(struct wt_status *s,
  1030. const char *color)
  1031. {
  1032. status_printf_ln(s, color,
  1033. _("You are in the middle of an am session."));
  1034. if (s->state.am_empty_patch)
  1035. status_printf_ln(s, color,
  1036. _("The current patch is empty."));
  1037. if (s->hints) {
  1038. if (!s->state.am_empty_patch)
  1039. status_printf_ln(s, color,
  1040. _(" (fix conflicts and then run \"git am --continue\")"));
  1041. status_printf_ln(s, color,
  1042. _(" (use \"git am --skip\" to skip this patch)"));
  1043. status_printf_ln(s, color,
  1044. _(" (use \"git am --abort\" to restore the original branch)"));
  1045. }
  1046. wt_longstatus_print_trailer(s);
  1047. }
  1048. static char *read_line_from_git_path(const char *filename)
  1049. {
  1050. struct strbuf buf = STRBUF_INIT;
  1051. FILE *fp = fopen_or_warn(git_path("%s", filename), "r");
  1052. if (!fp) {
  1053. strbuf_release(&buf);
  1054. return NULL;
  1055. }
  1056. strbuf_getline_lf(&buf, fp);
  1057. if (!fclose(fp)) {
  1058. return strbuf_detach(&buf, NULL);
  1059. } else {
  1060. strbuf_release(&buf);
  1061. return NULL;
  1062. }
  1063. }
  1064. static int split_commit_in_progress(struct wt_status *s)
  1065. {
  1066. int split_in_progress = 0;
  1067. char *head, *orig_head, *rebase_amend, *rebase_orig_head;
  1068. if ((!s->amend && !s->nowarn && !s->workdir_dirty) ||
  1069. !s->branch || strcmp(s->branch, "HEAD"))
  1070. return 0;
  1071. head = read_line_from_git_path("HEAD");
  1072. orig_head = read_line_from_git_path("ORIG_HEAD");
  1073. rebase_amend = read_line_from_git_path("rebase-merge/amend");
  1074. rebase_orig_head = read_line_from_git_path("rebase-merge/orig-head");
  1075. if (!head || !orig_head || !rebase_amend || !rebase_orig_head)
  1076. ; /* fall through, no split in progress */
  1077. else if (!strcmp(rebase_amend, rebase_orig_head))
  1078. split_in_progress = !!strcmp(head, rebase_amend);
  1079. else if (strcmp(orig_head, rebase_orig_head))
  1080. split_in_progress = 1;
  1081. free(head);
  1082. free(orig_head);
  1083. free(rebase_amend);
  1084. free(rebase_orig_head);
  1085. return split_in_progress;
  1086. }
  1087. /*
  1088. * Turn
  1089. * "pick d6a2f0303e897ec257dd0e0a39a5ccb709bc2047 some message"
  1090. * into
  1091. * "pick d6a2f03 some message"
  1092. *
  1093. * The function assumes that the line does not contain useless spaces
  1094. * before or after the command.
  1095. */
  1096. static void abbrev_sha1_in_line(struct strbuf *line)
  1097. {
  1098. struct strbuf **split;
  1099. int i;
  1100. if (starts_with(line->buf, "exec ") ||
  1101. starts_with(line->buf, "x ") ||
  1102. starts_with(line->buf, "label ") ||
  1103. starts_with(line->buf, "l "))
  1104. return;
  1105. split = strbuf_split_max(line, ' ', 3);
  1106. if (split[0] && split[1]) {
  1107. struct object_id oid;
  1108. /*
  1109. * strbuf_split_max left a space. Trim it and re-add
  1110. * it after abbreviation.
  1111. */
  1112. strbuf_trim(split[1]);
  1113. if (!get_oid(split[1]->buf, &oid)) {
  1114. strbuf_reset(split[1]);
  1115. strbuf_add_unique_abbrev(split[1], &oid,
  1116. DEFAULT_ABBREV);
  1117. strbuf_addch(split[1], ' ');
  1118. strbuf_reset(line);
  1119. for (i = 0; split[i]; i++)
  1120. strbuf_addbuf(line, split[i]);
  1121. }
  1122. }
  1123. strbuf_list_free(split);
  1124. }
  1125. static int read_rebase_todolist(const char *fname, struct string_list *lines)
  1126. {
  1127. struct strbuf line = STRBUF_INIT;
  1128. FILE *f = fopen(git_path("%s", fname), "r");
  1129. if (!f) {
  1130. if (errno == ENOENT)
  1131. return -1;
  1132. die_errno("Could not open file %s for reading",
  1133. git_path("%s", fname));
  1134. }
  1135. while (!strbuf_getline_lf(&line, f)) {
  1136. if (line.len && line.buf[0] == comment_line_char)
  1137. continue;
  1138. strbuf_trim(&line);
  1139. if (!line.len)
  1140. continue;
  1141. abbrev_sha1_in_line(&line);
  1142. string_list_append(lines, line.buf);
  1143. }
  1144. fclose(f);
  1145. strbuf_release(&line);
  1146. return 0;
  1147. }
  1148. static void show_rebase_information(struct wt_status *s,
  1149. const char *color)
  1150. {
  1151. if (s->state.rebase_interactive_in_progress) {
  1152. int i;
  1153. int nr_lines_to_show = 2;
  1154. struct string_list have_done = STRING_LIST_INIT_DUP;
  1155. struct string_list yet_to_do = STRING_LIST_INIT_DUP;
  1156. read_rebase_todolist("rebase-merge/done", &have_done);
  1157. if (read_rebase_todolist("rebase-merge/git-rebase-todo",
  1158. &yet_to_do))
  1159. status_printf_ln(s, color,
  1160. _("git-rebase-todo is missing."));
  1161. if (have_done.nr == 0)
  1162. status_printf_ln(s, color, _("No commands done."));
  1163. else {
  1164. status_printf_ln(s, color,
  1165. Q_("Last command done (%d command done):",
  1166. "Last commands done (%d commands done):",
  1167. have_done.nr),
  1168. have_done.nr);
  1169. for (i = (have_done.nr > nr_lines_to_show)
  1170. ? have_done.nr - nr_lines_to_show : 0;
  1171. i < have_done.nr;
  1172. i++)
  1173. status_printf_ln(s, color, " %s", have_done.items[i].string);
  1174. if (have_done.nr > nr_lines_to_show && s->hints)
  1175. status_printf_ln(s, color,
  1176. _(" (see more in file %s)"), git_path("rebase-merge/done"));
  1177. }
  1178. if (yet_to_do.nr == 0)
  1179. status_printf_ln(s, color,
  1180. _("No commands remaining."));
  1181. else {
  1182. status_printf_ln(s, color,
  1183. Q_("Next command to do (%d remaining command):",
  1184. "Next commands to do (%d remaining commands):",
  1185. yet_to_do.nr),
  1186. yet_to_do.nr);
  1187. for (i = 0; i < nr_lines_to_show && i < yet_to_do.nr; i++)
  1188. status_printf_ln(s, color, " %s", yet_to_do.items[i].string);
  1189. if (s->hints)
  1190. status_printf_ln(s, color,
  1191. _(" (use \"git rebase --edit-todo\" to view and edit)"));
  1192. }
  1193. string_list_clear(&yet_to_do, 0);
  1194. string_list_clear(&have_done, 0);
  1195. }
  1196. }
  1197. static void print_rebase_state(struct wt_status *s,
  1198. const char *color)
  1199. {
  1200. if (s->state.branch)
  1201. status_printf_ln(s, color,
  1202. _("You are currently rebasing branch '%s' on '%s'."),
  1203. s->state.branch,
  1204. s->state.onto);
  1205. else
  1206. status_printf_ln(s, color,
  1207. _("You are currently rebasing."));
  1208. }
  1209. static void show_rebase_in_progress(struct wt_status *s,
  1210. const char *color)
  1211. {
  1212. struct stat st;
  1213. show_rebase_information(s, color);
  1214. if (has_unmerged(s)) {
  1215. print_rebase_state(s, color);
  1216. if (s->hints) {
  1217. status_printf_ln(s, color,
  1218. _(" (fix conflicts and then run \"git rebase --continue\")"));
  1219. status_printf_ln(s, color,
  1220. _(" (use \"git rebase --skip\" to skip this patch)"));
  1221. status_printf_ln(s, color,
  1222. _(" (use \"git rebase --abort\" to check out the original branch)"));
  1223. }
  1224. } else if (s->state.rebase_in_progress ||
  1225. !stat(git_path_merge_msg(s->repo), &st)) {
  1226. print_rebase_state(s, color);
  1227. if (s->hints)
  1228. status_printf_ln(s, color,
  1229. _(" (all conflicts fixed: run \"git rebase --continue\")"));
  1230. } else if (split_commit_in_progress(s)) {
  1231. if (s->state.branch)
  1232. status_printf_ln(s, color,
  1233. _("You are currently splitting a commit while rebasing branch '%s' on '%s'."),
  1234. s->state.branch,
  1235. s->state.onto);
  1236. else
  1237. status_printf_ln(s, color,
  1238. _("You are currently splitting a commit during a rebase."));
  1239. if (s->hints)
  1240. status_printf_ln(s, color,
  1241. _(" (Once your working directory is clean, run \"git rebase --continue\")"));
  1242. } else {
  1243. if (s->state.branch)
  1244. status_printf_ln(s, color,
  1245. _("You are currently editing a commit while rebasing branch '%s' on '%s'."),
  1246. s->state.branch,
  1247. s->state.onto);
  1248. else
  1249. status_printf_ln(s, color,
  1250. _("You are currently editing a commit during a rebase."));
  1251. if (s->hints && !s->amend) {
  1252. status_printf_ln(s, color,
  1253. _(" (use \"git commit --amend\" to amend the current commit)"));
  1254. status_printf_ln(s, color,
  1255. _(" (use \"git rebase --continue\" once you are satisfied with your changes)"));
  1256. }
  1257. }
  1258. wt_longstatus_print_trailer(s);
  1259. }
  1260. static void show_cherry_pick_in_progress(struct wt_status *s,
  1261. const char *color)
  1262. {
  1263. if (is_null_oid(&s->state.cherry_pick_head_oid))
  1264. status_printf_ln(s, color,
  1265. _("Cherry-pick currently in progress."));
  1266. else
  1267. status_printf_ln(s, color,
  1268. _("You are currently cherry-picking commit %s."),
  1269. find_unique_abbrev(&s->state.cherry_pick_head_oid,
  1270. DEFAULT_ABBREV));
  1271. if (s->hints) {
  1272. if (has_unmerged(s))
  1273. status_printf_ln(s, color,
  1274. _(" (fix conflicts and run \"git cherry-pick --continue\")"));
  1275. else if (is_null_oid(&s->state.cherry_pick_head_oid))
  1276. status_printf_ln(s, color,
  1277. _(" (run \"git cherry-pick --continue\" to continue)"));
  1278. else
  1279. status_printf_ln(s, color,
  1280. _(" (all conflicts fixed: run \"git cherry-pick --continue\")"));
  1281. status_printf_ln(s, color,
  1282. _(" (use \"git cherry-pick --abort\" to cancel the cherry-pick operation)"));
  1283. }
  1284. wt_longstatus_print_trailer(s);
  1285. }
  1286. static void show_revert_in_progress(struct wt_status *s,
  1287. const char *color)
  1288. {
  1289. if (is_null_oid(&s->state.revert_head_oid))
  1290. status_printf_ln(s, color,
  1291. _("Revert currently in progress."));
  1292. else
  1293. status_printf_ln(s, color,
  1294. _("You are currently reverting commit %s."),
  1295. find_unique_abbrev(&s->state.revert_head_oid,
  1296. DEFAULT_ABBREV));
  1297. if (s->hints) {
  1298. if (has_unmerged(s))
  1299. status_printf_ln(s, color,
  1300. _(" (fix conflicts and run \"git revert --continue\")"));
  1301. else if (is_null_oid(&s->state.revert_head_oid))
  1302. status_printf_ln(s, color,
  1303. _(" (run \"git revert --continue\" to continue)"));
  1304. else
  1305. status_printf_ln(s, color,
  1306. _(" (all conflicts fixed: run \"git revert --continue\")"));
  1307. status_printf_ln(s, color,
  1308. _(" (use \"git revert --abort\" to cancel the revert operation)"));
  1309. }
  1310. wt_longstatus_print_trailer(s);
  1311. }
  1312. static void show_bisect_in_progress(struct wt_status *s,
  1313. const char *color)
  1314. {
  1315. if (s->state.branch)
  1316. status_printf_ln(s, color,
  1317. _("You are currently bisecting, started from branch '%s'."),
  1318. s->state.branch);
  1319. else
  1320. status_printf_ln(s, color,
  1321. _("You are currently bisecting."));
  1322. if (s->hints)
  1323. status_printf_ln(s, color,
  1324. _(" (use \"git bisect reset\" to get back to the original branch)"));
  1325. wt_longstatus_print_trailer(s);
  1326. }
  1327. /*
  1328. * Extract branch information from rebase/bisect
  1329. */
  1330. static char *get_branch(const struct worktree *wt, const char *path)
  1331. {
  1332. struct strbuf sb = STRBUF_INIT;
  1333. struct object_id oid;
  1334. const char *branch_name;
  1335. if (strbuf_read_file(&sb, worktree_git_path(wt, "%s", path), 0) <= 0)
  1336. goto got_nothing;
  1337. while (sb.len && sb.buf[sb.len - 1] == '\n')
  1338. strbuf_setlen(&sb, sb.len - 1);
  1339. if (!sb.len)
  1340. goto got_nothing;
  1341. if (skip_prefix(sb.buf, "refs/heads/", &branch_name))
  1342. strbuf_remove(&sb, 0, branch_name - sb.buf);
  1343. else if (starts_with(sb.buf, "refs/"))
  1344. ;
  1345. else if (!get_oid_hex(sb.buf, &oid)) {
  1346. strbuf_reset(&sb);
  1347. strbuf_add_unique_abbrev(&sb, &oid, DEFAULT_ABBREV);
  1348. } else if (!strcmp(sb.buf, "detached HEAD")) /* rebase */
  1349. goto got_nothing;
  1350. else /* bisect */
  1351. ;
  1352. return strbuf_detach(&sb, NULL);
  1353. got_nothing:
  1354. strbuf_release(&sb);
  1355. return NULL;
  1356. }
  1357. struct grab_1st_switch_cbdata {
  1358. struct strbuf buf;
  1359. struct object_id noid;
  1360. };
  1361. static int grab_1st_switch(struct object_id *ooid, struct object_id *noid,
  1362. const char *email, timestamp_t timestamp, int tz,
  1363. const char *message, void *cb_data)
  1364. {
  1365. struct grab_1st_switch_cbdata *cb = cb_data;
  1366. const char *target = NULL, *end;
  1367. if (!skip_prefix(message, "checkout: moving from ", &message))
  1368. return 0;
  1369. target = strstr(message, " to ");
  1370. if (!target)
  1371. return 0;
  1372. target += strlen(" to ");
  1373. strbuf_reset(&cb->buf);
  1374. oidcpy(&cb->noid, noid);
  1375. end = strchrnul(target, '\n');
  1376. strbuf_add(&cb->buf, target, end - target);
  1377. if (!strcmp(cb->buf.buf, "HEAD")) {
  1378. /* HEAD is relative. Resolve it to the right reflog entry. */
  1379. strbuf_reset(&cb->buf);
  1380. strbuf_add_unique_abbrev(&cb->buf, noid, DEFAULT_ABBREV);
  1381. }
  1382. return 1;
  1383. }
  1384. static void wt_status_get_detached_from(struct repository *r,
  1385. struct wt_status_state *state)
  1386. {
  1387. struct grab_1st_switch_cbdata cb;
  1388. struct commit *commit;
  1389. struct object_id oid;
  1390. char *ref = NULL;
  1391. strbuf_init(&cb.buf, 0);
  1392. if (for_each_reflog_ent_reverse("HEAD", grab_1st_switch, &cb) <= 0) {
  1393. strbuf_release(&cb.buf);
  1394. return;
  1395. }
  1396. if (dwim_ref(cb.buf.buf, cb.buf.len, &oid, &ref) == 1 &&
  1397. /* sha1 is a commit? match without further lookup */
  1398. (oideq(&cb.noid, &oid) ||
  1399. /* perhaps sha1 is a tag, try to dereference to a commit */
  1400. ((commit = lookup_commit_reference_gently(r, &oid, 1)) != NULL &&
  1401. oideq(&cb.noid, &commit->object.oid)))) {
  1402. const char *from = ref;
  1403. if (!skip_prefix(from, "refs/tags/", &from))
  1404. skip_prefix(from, "refs/remotes/", &from);
  1405. state->detached_from = xstrdup(from);
  1406. } else
  1407. state->detached_from =
  1408. xstrdup(find_unique_abbrev(&cb.noid, DEFAULT_ABBREV));
  1409. oidcpy(&state->detached_oid, &cb.noid);
  1410. state->detached_at = !get_oid("HEAD", &oid) &&
  1411. oideq(&oid, &state->detached_oid);
  1412. free(ref);
  1413. strbuf_release(&cb.buf);
  1414. }
  1415. int wt_status_check_rebase(const struct worktree *wt,
  1416. struct wt_status_state *state)
  1417. {
  1418. struct stat st;
  1419. if (!stat(worktree_git_path(wt, "rebase-apply"), &st)) {
  1420. if (!stat(worktree_git_path(wt, "rebase-apply/applying"), &st)) {
  1421. state->am_in_progress = 1;
  1422. if (!stat(worktree_git_path(wt, "rebase-apply/patch"), &st) && !st.st_size)
  1423. state->am_empty_patch = 1;
  1424. } else {
  1425. state->rebase_in_progress = 1;
  1426. state->branch = get_branch(wt, "rebase-apply/head-name");
  1427. state->onto = get_branch(wt, "rebase-apply/onto");
  1428. }
  1429. } else if (!stat(worktree_git_path(wt, "rebase-merge"), &st)) {
  1430. if (!stat(worktree_git_path(wt, "rebase-merge/interactive"), &st))
  1431. state->rebase_interactive_in_progress = 1;
  1432. else
  1433. state->rebase_in_progress = 1;
  1434. state->branch = get_branch(wt, "rebase-merge/head-name");
  1435. state->onto = get_branch(wt, "rebase-merge/onto");
  1436. } else
  1437. return 0;
  1438. return 1;
  1439. }
  1440. int wt_status_check_bisect(const struct worktree *wt,
  1441. struct wt_status_state *state)
  1442. {
  1443. struct stat st;
  1444. if (!stat(worktree_git_path(wt, "BISECT_LOG"), &st)) {
  1445. state->bisect_in_progress = 1;
  1446. state->branch = get_branch(wt, "BISECT_START");
  1447. return 1;
  1448. }
  1449. return 0;
  1450. }
  1451. void wt_status_get_state(struct repository *r,
  1452. struct wt_status_state *state,
  1453. int get_detached_from)
  1454. {
  1455. struct stat st;
  1456. struct object_id oid;
  1457. enum replay_action action;
  1458. if (!stat(git_path_merge_head(r), &st)) {
  1459. wt_status_check_rebase(NULL, state);
  1460. state->merge_in_progress = 1;
  1461. } else if (wt_status_check_rebase(NULL, state)) {
  1462. ; /* all set */
  1463. } else if (!stat(git_path_cherry_pick_head(r), &st) &&
  1464. !get_oid("CHERRY_PICK_HEAD", &oid)) {
  1465. state->cherry_pick_in_progress = 1;
  1466. oidcpy(&state->cherry_pick_head_oid, &oid);
  1467. }
  1468. wt_status_check_bisect(NULL, state);
  1469. if (!stat(git_path_revert_head(r), &st) &&
  1470. !get_oid("REVERT_HEAD", &oid)) {
  1471. state->revert_in_progress = 1;
  1472. oidcpy(&state->revert_head_oid, &oid);
  1473. }
  1474. if (!sequencer_get_last_command(r, &action)) {
  1475. if (action == REPLAY_PICK) {
  1476. state->cherry_pick_in_progress = 1;
  1477. oidcpy(&state->cherry_pick_head_oid, &null_oid);
  1478. } else {
  1479. state->revert_in_progress = 1;
  1480. oidcpy(&state->revert_head_oid, &null_oid);
  1481. }
  1482. }
  1483. if (get_detached_from)
  1484. wt_status_get_detached_from(r, state);
  1485. }
  1486. static void wt_longstatus_print_state(struct wt_status *s)
  1487. {
  1488. const char *state_color = color(WT_STATUS_HEADER, s);
  1489. struct wt_status_state *state = &s->state;
  1490. if (state->merge_in_progress) {
  1491. if (state->rebase_interactive_in_progress) {
  1492. show_rebase_information(s, state_color);
  1493. fputs("\n", s->fp);
  1494. }
  1495. show_merge_in_progress(s, state_color);
  1496. } else if (state->am_in_progress)
  1497. show_am_in_progress(s, state_color);
  1498. else if (state->rebase_in_progress || state->rebase_interactive_in_progress)
  1499. show_rebase_in_progress(s, state_color);
  1500. else if (state->cherry_pick_in_progress)
  1501. show_cherry_pick_in_progress(s, state_color);
  1502. else if (state->revert_in_progress)
  1503. show_revert_in_progress(s, state_color);
  1504. if (state->bisect_in_progress)
  1505. show_bisect_in_progress(s, state_color);
  1506. }
  1507. static void wt_longstatus_print(struct wt_status *s)
  1508. {
  1509. const char *branch_color = color(WT_STATUS_ONBRANCH, s);
  1510. const char *branch_status_color = color(WT_STATUS_HEADER, s);
  1511. if (s->branch) {
  1512. const char *on_what = _("On branch ");
  1513. const char *branch_name = s->branch;
  1514. if (!strcmp(branch_name, "HEAD")) {
  1515. branch_status_color = color(WT_STATUS_NOBRANCH, s);
  1516. if (s->state.rebase_in_progress ||
  1517. s->state.rebase_interactive_in_progress) {
  1518. if (s->state.rebase_interactive_in_progress)
  1519. on_what = _("interactive rebase in progress; onto ");
  1520. else
  1521. on_what = _("rebase in progress; onto ");
  1522. branch_name = s->state.onto;
  1523. } else if (s->state.detached_from) {
  1524. branch_name = s->state.detached_from;
  1525. if (s->state.detached_at)
  1526. on_what = HEAD_DETACHED_AT;
  1527. else
  1528. on_what = HEAD_DETACHED_FROM;
  1529. } else {
  1530. branch_name = "";
  1531. on_what = _("Not currently on any branch.");
  1532. }
  1533. } else
  1534. skip_prefix(branch_name, "refs/heads/", &branch_name);
  1535. status_printf(s, color(WT_STATUS_HEADER, s), "%s", "");
  1536. status_printf_more(s, branch_status_color, "%s", on_what);
  1537. status_printf_more(s, branch_color, "%s\n", branch_name);
  1538. if (!s->is_initial)
  1539. wt_longstatus_print_tracking(s);
  1540. }
  1541. wt_longstatus_print_state(s);
  1542. if (s->is_initial) {
  1543. status_printf_ln(s, color(WT_STATUS_HEADER, s), "%s", "");
  1544. status_printf_ln(s, color(WT_STATUS_HEADER, s),
  1545. s->commit_template
  1546. ? _("Initial commit")
  1547. : _("No commits yet"));
  1548. status_printf_ln(s, color(WT_STATUS_HEADER, s), "%s", "");
  1549. }
  1550. wt_longstatus_print_updated(s);
  1551. wt_longstatus_print_unmerged(s);
  1552. wt_longstatus_print_changed(s);
  1553. if (s->submodule_summary &&
  1554. (!s->ignore_submodule_arg ||
  1555. strcmp(s->ignore_submodule_arg, "all"))) {
  1556. wt_longstatus_print_submodule_summary(s, 0); /* staged */
  1557. wt_longstatus_print_submodule_summary(s, 1); /* unstaged */
  1558. }
  1559. if (s->show_untracked_files) {
  1560. wt_longstatus_print_other(s, &s->untracked, _("Untracked files"), "add");
  1561. if (s->show_ignored_mode)
  1562. wt_longstatus_print_other(s, &s->ignored, _("Ignored files"), "add -f");
  1563. if (advice_status_u_option && 2000 < s->untracked_in_ms) {
  1564. status_printf_ln(s, GIT_COLOR_NORMAL, "%s", "");
  1565. status_printf_ln(s, GIT_COLOR_NORMAL,
  1566. _("It took %.2f seconds to enumerate untracked files. 'status -uno'\n"
  1567. "may speed it up, but you have to be careful not to forget to add\n"
  1568. "new files yourself (see 'git help status')."),
  1569. s->untracked_in_ms / 1000.0);
  1570. }
  1571. } else if (s->committable)
  1572. status_printf_ln(s, GIT_COLOR_NORMAL, _("Untracked files not listed%s"),
  1573. s->hints
  1574. ? _(" (use -u option to show untracked files)") : "");
  1575. if (s->verbose)
  1576. wt_longstatus_print_verbose(s);
  1577. if (!s->committable) {
  1578. if (s->amend)
  1579. status_printf_ln(s, GIT_COLOR_NORMAL, _("No changes"));
  1580. else if (s->nowarn)
  1581. ; /* nothing */
  1582. else if (s->workdir_dirty) {
  1583. if (s->hints)
  1584. printf(_("no changes added to commit "
  1585. "(use \"git add\" and/or \"git commit -a\")\n"));
  1586. else
  1587. printf(_("no changes added to commit\n"));
  1588. } else if (s->untracked.nr) {
  1589. if (s->hints)
  1590. printf(_("nothing added to commit but untracked files "
  1591. "present (use \"git add\" to track)\n"));
  1592. else
  1593. printf(_("nothing added to commit but untracked files present\n"));
  1594. } else if (s->is_initial) {
  1595. if (s->hints)
  1596. printf(_("nothing to commit (create/copy files "
  1597. "and use \"git add\" to track)\n"));
  1598. else
  1599. printf(_("nothing to commit\n"));
  1600. } else if (!s->show_untracked_files) {
  1601. if (s->hints)
  1602. printf(_("nothing to commit (use -u to show untracked files)\n"));
  1603. else
  1604. printf(_("nothing to commit\n"));
  1605. } else
  1606. printf(_("nothing to commit, working tree clean\n"));
  1607. }
  1608. if(s->show_stash)
  1609. wt_longstatus_print_stash_summary(s);
  1610. }
  1611. static void wt_shortstatus_unmerged(struct string_list_item *it,
  1612. struct wt_status *s)
  1613. {
  1614. struct wt_status_change_data *d = it->util;
  1615. const char *how = "??";
  1616. switch (d->stagemask) {
  1617. case 1: how = "DD"; break; /* both deleted */
  1618. case 2: how = "AU"; break; /* added by us */
  1619. case 3: how = "UD"; break; /* deleted by them */
  1620. case 4: how = "UA"; break; /* added by them */
  1621. case 5: how = "DU"; break; /* deleted by us */
  1622. case 6: how = "AA"; break; /* both added */
  1623. case 7: how = "UU"; break; /* both modified */
  1624. }
  1625. color_fprintf(s->fp, color(WT_STATUS_UNMERGED, s), "%s", how);
  1626. if (s->null_termination) {
  1627. fprintf(stdout, " %s%c", it->string, 0);
  1628. } else {
  1629. struct strbuf onebuf = STRBUF_INIT;
  1630. const char *one;
  1631. one = quote_path(it->string, s->prefix, &onebuf);
  1632. printf(" %s\n", one);
  1633. strbuf_release(&onebuf);
  1634. }
  1635. }
  1636. static void wt_shortstatus_status(struct string_list_item *it,
  1637. struct wt_status *s)
  1638. {
  1639. struct wt_status_change_data *d = it->util;
  1640. if (d->index_status)
  1641. color_fprintf(s->fp, color(WT_STATUS_UPDATED, s), "%c", d->index_status);
  1642. else
  1643. putchar(' ');
  1644. if (d->worktree_status)
  1645. color_fprintf(s->fp, color(WT_STATUS_CHANGED, s), "%c", d->worktree_status);
  1646. else
  1647. putchar(' ');
  1648. putchar(' ');
  1649. if (s->null_termination) {
  1650. fprintf(stdout, "%s%c", it->string, 0);
  1651. if (d->rename_source)
  1652. fprintf(stdout, "%s%c", d->rename_source, 0);
  1653. } else {
  1654. struct strbuf onebuf = STRBUF_INIT;
  1655. const char *one;
  1656. if (d->rename_source) {
  1657. one = quote_path(d->rename_source, s->prefix, &onebuf);
  1658. if (*one != '"' && strchr(one, ' ') != NULL) {
  1659. putchar('"');
  1660. strbuf_addch(&onebuf, '"');
  1661. one = onebuf.buf;
  1662. }
  1663. printf("%s -> ", one);
  1664. strbuf_release(&onebuf);
  1665. }
  1666. one = quote_path(it->string, s->prefix, &onebuf);
  1667. if (*one != '"' && strchr(one, ' ') != NULL) {
  1668. putchar('"');
  1669. strbuf_addch(&onebuf, '"');
  1670. one = onebuf.buf;
  1671. }
  1672. printf("%s\n", one);
  1673. strbuf_release(&onebuf);
  1674. }
  1675. }
  1676. static void wt_shortstatus_other(struct string_list_item *it,
  1677. struct wt_status *s, const char *sign)
  1678. {
  1679. if (s->null_termination) {
  1680. fprintf(stdout, "%s %s%c", sign, it->string, 0);
  1681. } else {
  1682. struct strbuf onebuf = STRBUF_INIT;
  1683. const char *one;
  1684. one = quote_path(it->string, s->prefix, &onebuf);
  1685. color_fprintf(s->fp, color(WT_STATUS_UNTRACKED, s), "%s", sign);
  1686. printf(" %s\n", one);
  1687. strbuf_release(&onebuf);
  1688. }
  1689. }
  1690. static void wt_shortstatus_print_tracking(struct wt_status *s)
  1691. {
  1692. struct branch *branch;
  1693. const char *header_color = color(WT_STATUS_HEADER, s);
  1694. const char *branch_color_local = color(WT_STATUS_LOCAL_BRANCH, s);
  1695. const char *branch_color_remote = color(WT_STATUS_REMOTE_BRANCH, s);
  1696. const char *base;
  1697. char *short_base;
  1698. const char *branch_name;
  1699. int num_ours, num_theirs, sti;
  1700. int upstream_is_gone = 0;
  1701. color_fprintf(s->fp, color(WT_STATUS_HEADER, s), "## ");
  1702. if (!s->branch)
  1703. return;
  1704. branch_name = s->branch;
  1705. #define LABEL(string) (s->no_gettext ? (string) : _(string))
  1706. if (s->is_initial)
  1707. color_fprintf(s->fp, header_color, LABEL(N_("No commits yet on ")));
  1708. if (!strcmp(s->branch, "HEAD")) {
  1709. color_fprintf(s->fp, color(WT_STATUS_NOBRANCH, s), "%s",
  1710. LABEL(N_("HEAD (no branch)")));
  1711. goto conclude;
  1712. }
  1713. skip_prefix(branch_name, "refs/heads/", &branch_name);
  1714. branch = branch_get(branch_name);
  1715. color_fprintf(s->fp, branch_color_local, "%s", branch_name);
  1716. sti = stat_tracking_info(branch, &num_ours, &num_theirs, &base,
  1717. 0, s->ahead_behind_flags);
  1718. if (sti < 0) {
  1719. if (!base)
  1720. goto conclude;
  1721. upstream_is_gone = 1;
  1722. }
  1723. short_base = shorten_unambiguous_ref(base, 0);
  1724. color_fprintf(s->fp, header_color, "...");
  1725. color_fprintf(s->fp, branch_color_remote, "%s", short_base);
  1726. free(short_base);
  1727. if (!upstream_is_gone && !sti)
  1728. goto conclude;
  1729. color_fprintf(s->fp, header_color, " [");
  1730. if (upstream_is_gone) {
  1731. color_fprintf(s->fp, header_color, LABEL(N_("gone")));
  1732. } else if (s->ahead_behind_flags == AHEAD_BEHIND_QUICK) {
  1733. color_fprintf(s->fp, header_color, LABEL(N_("different")));
  1734. } else if (!num_ours) {
  1735. color_fprintf(s->fp, header_color, LABEL(N_("behind ")));
  1736. color_fprintf(s->fp, branch_color_remote, "%d", num_theirs);
  1737. } else if (!num_theirs) {
  1738. color_fprintf(s->fp, header_color, LABEL(N_("ahead ")));
  1739. color_fprintf(s->fp, branch_color_local, "%d", num_ours);
  1740. } else {
  1741. color_fprintf(s->fp, header_color, LABEL(N_("ahead ")));
  1742. color_fprintf(s->fp, branch_color_local, "%d", num_ours);
  1743. color_fprintf(s->fp, header_color, ", %s", LABEL(N_("behind ")));
  1744. color_fprintf(s->fp, branch_color_remote, "%d", num_theirs);
  1745. }
  1746. color_fprintf(s->fp, header_color, "]");
  1747. conclude:
  1748. fputc(s->null_termination ? '\0' : '\n', s->fp);
  1749. }
  1750. static void wt_shortstatus_print(struct wt_status *s)
  1751. {
  1752. struct string_list_item *it;
  1753. if (s->show_branch)
  1754. wt_shortstatus_print_tracking(s);
  1755. for_each_string_list_item(it, &s->change) {
  1756. struct wt_status_change_data *d = it->util;
  1757. if (d->stagemask)
  1758. wt_shortstatus_unmerged(it, s);
  1759. else
  1760. wt_shortstatus_status(it, s);
  1761. }
  1762. for_each_string_list_item(it, &s->untracked)
  1763. wt_shortstatus_other(it, s, "??");
  1764. for_each_string_list_item(it, &s->ignored)
  1765. wt_shortstatus_other(it, s, "!!");
  1766. }
  1767. static void wt_porcelain_print(struct wt_status *s)
  1768. {
  1769. s->use_color = 0;
  1770. s->relative_paths = 0;
  1771. s->prefix = NULL;
  1772. s->no_gettext = 1;
  1773. wt_shortstatus_print(s);
  1774. }
  1775. /*
  1776. * Print branch information for porcelain v2 output. These lines
  1777. * are printed when the '--branch' parameter is given.
  1778. *
  1779. * # branch.oid <commit><eol>
  1780. * # branch.head <head><eol>
  1781. * [# branch.upstream <upstream><eol>
  1782. * [# branch.ab +<ahead> -<behind><eol>]]
  1783. *
  1784. * <commit> ::= the current commit hash or the the literal
  1785. * "(initial)" to indicate an initialized repo
  1786. * with no commits.
  1787. *
  1788. * <head> ::= <branch_name> the current branch name or
  1789. * "(detached)" literal when detached head or
  1790. * "(unknown)" when something is wrong.
  1791. *
  1792. * <upstream> ::= the upstream branch name, when set.
  1793. *
  1794. * <ahead> ::= integer ahead value or '?'.
  1795. *
  1796. * <behind> ::= integer behind value or '?'.
  1797. *
  1798. * The end-of-line is defined by the -z flag.
  1799. *
  1800. * <eol> ::= NUL when -z,
  1801. * LF when NOT -z.
  1802. *
  1803. * When an upstream is set and present, the 'branch.ab' line will
  1804. * be printed with the ahead/behind counts for the branch and the
  1805. * upstream. When AHEAD_BEHIND_QUICK is requested and the branches
  1806. * are different, '?' will be substituted for the actual count.
  1807. */
  1808. static void wt_porcelain_v2_print_tracking(struct wt_status *s)
  1809. {
  1810. struct branch *branch;
  1811. const char *base;
  1812. const char *branch_name;
  1813. int ab_info, nr_ahead, nr_behind;
  1814. char eol = s->null_termination ? '\0' : '\n';
  1815. fprintf(s->fp, "# branch.oid %s%c",
  1816. (s->is_initial ? "(initial)" : oid_to_hex(&s->oid_commit)),
  1817. eol);
  1818. if (!s->branch)
  1819. fprintf(s->fp, "# branch.head %s%c", "(unknown)", eol);
  1820. else {
  1821. if (!strcmp(s->branch, "HEAD")) {
  1822. fprintf(s->fp, "# branch.head %s%c", "(detached)", eol);
  1823. if (s->state.rebase_in_progress ||
  1824. s->state.rebase_interactive_in_progress)
  1825. branch_name = s->state.onto;
  1826. else if (s->state.detached_from)
  1827. branch_name = s->state.detached_from;
  1828. else
  1829. branch_name = "";
  1830. } else {
  1831. branch_name = NULL;
  1832. skip_prefix(s->branch, "refs/heads/", &branch_name);
  1833. fprintf(s->fp, "# branch.head %s%c", branch_name, eol);
  1834. }
  1835. /* Lookup stats on the upstream tracking branch, if set. */
  1836. branch = branch_get(branch_name);
  1837. base = NULL;
  1838. ab_info = stat_tracking_info(branch, &nr_ahead, &nr_behind,
  1839. &base, 0, s->ahead_behind_flags);
  1840. if (base) {
  1841. base = shorten_unambiguous_ref(base, 0);
  1842. fprintf(s->fp, "# branch.upstream %s%c", base, eol);
  1843. free((char *)base);
  1844. if (ab_info > 0) {
  1845. /* different */
  1846. if (nr_ahead || nr_behind)
  1847. fprintf(s->fp, "# branch.ab +%d -%d%c",
  1848. nr_ahead, nr_behind, eol);
  1849. else
  1850. fprintf(s->fp, "# branch.ab +? -?%c",
  1851. eol);
  1852. } else if (!ab_info) {
  1853. /* same */
  1854. fprintf(s->fp, "# branch.ab +0 -0%c", eol);
  1855. }
  1856. }
  1857. }
  1858. }
  1859. /*
  1860. * Convert various submodule status values into a
  1861. * fixed-length string of characters in the buffer provided.
  1862. */
  1863. static void wt_porcelain_v2_submodule_state(
  1864. struct wt_status_change_data *d,
  1865. char sub[5])
  1866. {
  1867. if (S_ISGITLINK(d->mode_head) ||
  1868. S_ISGITLINK(d->mode_index) ||
  1869. S_ISGITLINK(d->mode_worktree)) {
  1870. sub[0] = 'S';
  1871. sub[1] = d->new_submodule_commits ? 'C' : '.';
  1872. sub[2] = (d->dirty_submodule & DIRTY_SUBMODULE_MODIFIED) ? 'M' : '.';
  1873. sub[3] = (d->dirty_submodule & DIRTY_SUBMODULE_UNTRACKED) ? 'U' : '.';
  1874. } else {
  1875. sub[0] = 'N';
  1876. sub[1] = '.';
  1877. sub[2] = '.';
  1878. sub[3] = '.';
  1879. }
  1880. sub[4] = 0;
  1881. }
  1882. /*
  1883. * Fix-up changed entries before we print them.
  1884. */
  1885. static void wt_porcelain_v2_fix_up_changed(struct string_list_item *it)
  1886. {
  1887. struct wt_status_change_data *d = it->util;
  1888. if (!d->index_status) {
  1889. /*
  1890. * This entry is unchanged in the index (relative to the head).
  1891. * Therefore, the collect_updated_cb was never called for this
  1892. * entry (during the head-vs-index scan) and so the head column
  1893. * fields were never set.
  1894. *
  1895. * We must have data for the index column (from the
  1896. * index-vs-worktree scan (otherwise, this entry should not be
  1897. * in the list of changes)).
  1898. *
  1899. * Copy index column fields to the head column, so that our
  1900. * output looks complete.
  1901. */
  1902. assert(d->mode_head == 0);
  1903. d->mode_head = d->mode_index;
  1904. oidcpy(&d->oid_head, &d->oid_index);
  1905. }
  1906. if (!d->worktree_status) {
  1907. /*
  1908. * This entry is unchanged in the worktree (relative to the index).
  1909. * Therefore, the collect_changed_cb was never called for this entry
  1910. * (during the index-vs-worktree scan) and so the worktree column
  1911. * fields were never set.
  1912. *
  1913. * We must have data for the index column (from the head-vs-index
  1914. * scan).
  1915. *
  1916. * Copy the index column fields to the worktree column so that
  1917. * our output looks complete.
  1918. *
  1919. * Note that we only have a mode field in the worktree column
  1920. * because the scan code tries really hard to not have to compute it.
  1921. */
  1922. assert(d->mode_worktree == 0);
  1923. d->mode_worktree = d->mode_index;
  1924. }
  1925. }
  1926. /*
  1927. * Print porcelain v2 info for tracked entries with changes.
  1928. */
  1929. static void wt_porcelain_v2_print_changed_entry(
  1930. struct string_list_item *it,
  1931. struct wt_status *s)
  1932. {
  1933. struct wt_status_change_data *d = it->util;
  1934. struct strbuf buf = STRBUF_INIT;
  1935. struct strbuf buf_from = STRBUF_INIT;
  1936. const char *path = NULL;
  1937. const char *path_from = NULL;
  1938. char key[3];
  1939. char submodule_token[5];
  1940. char sep_char, eol_char;
  1941. wt_porcelain_v2_fix_up_changed(it);
  1942. wt_porcelain_v2_submodule_state(d, submodule_token);
  1943. key[0] = d->index_status ? d->index_status : '.';
  1944. key[1] = d->worktree_status ? d->worktree_status : '.';
  1945. key[2] = 0;
  1946. if (s->null_termination) {
  1947. /*
  1948. * In -z mode, we DO NOT C-quote pathnames. Current path is ALWAYS first.
  1949. * A single NUL character separates them.
  1950. */
  1951. sep_char = '\0';
  1952. eol_char = '\0';
  1953. path = it->string;
  1954. path_from = d->rename_source;
  1955. } else {
  1956. /*
  1957. * Path(s) are C-quoted if necessary. Current path is ALWAYS first.
  1958. * The source path is only present when necessary.
  1959. * A single TAB separates them (because paths can contain spaces
  1960. * which are not escaped and C-quoting does escape TAB characters).
  1961. */
  1962. sep_char = '\t';
  1963. eol_char = '\n';
  1964. path = quote_path(it->string, s->prefix, &buf);
  1965. if (d->rename_source)
  1966. path_from = quote_path(d->rename_source, s->prefix, &buf_from);
  1967. }
  1968. if (path_from)
  1969. fprintf(s->fp, "2 %s %s %06o %06o %06o %s %s %c%d %s%c%s%c",
  1970. key, submodule_token,
  1971. d->mode_head, d->mode_index, d->mode_worktree,
  1972. oid_to_hex(&d->oid_head), oid_to_hex(&d->oid_index),
  1973. d->rename_status, d->rename_score,
  1974. path, sep_char, path_from, eol_char);
  1975. else
  1976. fprintf(s->fp, "1 %s %s %06o %06o %06o %s %s %s%c",
  1977. key, submodule_token,
  1978. d->mode_head, d->mode_index, d->mode_worktree,
  1979. oid_to_hex(&d->oid_head), oid_to_hex(&d->oid_index),
  1980. path, eol_char);
  1981. strbuf_release(&buf);
  1982. strbuf_release(&buf_from);
  1983. }
  1984. /*
  1985. * Print porcelain v2 status info for unmerged entries.
  1986. */
  1987. static void wt_porcelain_v2_print_unmerged_entry(
  1988. struct string_list_item *it,
  1989. struct wt_status *s)
  1990. {
  1991. struct wt_status_change_data *d = it->util;
  1992. struct index_state *istate = s->repo->index;
  1993. const struct cache_entry *ce;
  1994. struct strbuf buf_index = STRBUF_INIT;
  1995. const char *path_index = NULL;
  1996. int pos, stage, sum;
  1997. struct {
  1998. int mode;
  1999. struct object_id oid;
  2000. } stages[3];
  2001. char *key;
  2002. char submodule_token[5];
  2003. char unmerged_prefix = 'u';
  2004. char eol_char = s->null_termination ? '\0' : '\n';
  2005. wt_porcelain_v2_submodule_state(d, submodule_token);
  2006. switch (d->stagemask) {
  2007. case 1: key = "DD"; break; /* both deleted */
  2008. case 2: key = "AU"; break; /* added by us */
  2009. case 3: key = "UD"; break; /* deleted by them */
  2010. case 4: key = "UA"; break; /* added by them */
  2011. case 5: key = "DU"; break; /* deleted by us */
  2012. case 6: key = "AA"; break; /* both added */
  2013. case 7: key = "UU"; break; /* both modified */
  2014. default:
  2015. BUG("unhandled unmerged status %x", d->stagemask);
  2016. }
  2017. /*
  2018. * Disregard d.aux.porcelain_v2 data that we accumulated
  2019. * for the head and index columns during the scans and
  2020. * replace with the actual stage data.
  2021. *
  2022. * Note that this is a last-one-wins for each the individual
  2023. * stage [123] columns in the event of multiple cache entries
  2024. * for same stage.
  2025. */
  2026. memset(stages, 0, sizeof(stages));
  2027. sum = 0;
  2028. pos = index_name_pos(istate, it->string, strlen(it->string));
  2029. assert(pos < 0);
  2030. pos = -pos-1;
  2031. while (pos < istate->cache_nr) {
  2032. ce = istate->cache[pos++];
  2033. stage = ce_stage(ce);
  2034. if (strcmp(ce->name, it->string) || !stage)
  2035. break;
  2036. stages[stage - 1].mode = ce->ce_mode;
  2037. oidcpy(&stages[stage - 1].oid, &ce->oid);
  2038. sum |= (1 << (stage - 1));
  2039. }
  2040. if (sum != d->stagemask)
  2041. BUG("observed stagemask 0x%x != expected stagemask 0x%x", sum, d->stagemask);
  2042. if (s->null_termination)
  2043. path_index = it->string;
  2044. else
  2045. path_index = quote_path(it->string, s->prefix, &buf_index);
  2046. fprintf(s->fp, "%c %s %s %06o %06o %06o %06o %s %s %s %s%c",
  2047. unmerged_prefix, key, submodule_token,
  2048. stages[0].mode, /* stage 1 */
  2049. stages[1].mode, /* stage 2 */
  2050. stages[2].mode, /* stage 3 */
  2051. d->mode_worktree,
  2052. oid_to_hex(&stages[0].oid), /* stage 1 */
  2053. oid_to_hex(&stages[1].oid), /* stage 2 */
  2054. oid_to_hex(&stages[2].oid), /* stage 3 */
  2055. path_index,
  2056. eol_char);
  2057. strbuf_release(&buf_index);
  2058. }
  2059. /*
  2060. * Print porcelain V2 status info for untracked and ignored entries.
  2061. */
  2062. static void wt_porcelain_v2_print_other(
  2063. struct string_list_item *it,
  2064. struct wt_status *s,
  2065. char prefix)
  2066. {
  2067. struct strbuf buf = STRBUF_INIT;
  2068. const char *path;
  2069. char eol_char;
  2070. if (s->null_termination) {
  2071. path = it->string;
  2072. eol_char = '\0';
  2073. } else {
  2074. path = quote_path(it->string, s->prefix, &buf);
  2075. eol_char = '\n';
  2076. }
  2077. fprintf(s->fp, "%c %s%c", prefix, path, eol_char);
  2078. strbuf_release(&buf);
  2079. }
  2080. /*
  2081. * Print porcelain V2 status.
  2082. *
  2083. * [<v2_branch>]
  2084. * [<v2_changed_items>]*
  2085. * [<v2_unmerged_items>]*
  2086. * [<v2_untracked_items>]*
  2087. * [<v2_ignored_items>]*
  2088. *
  2089. */
  2090. static void wt_porcelain_v2_print(struct wt_status *s)
  2091. {
  2092. struct wt_status_change_data *d;
  2093. struct string_list_item *it;
  2094. int i;
  2095. if (s->show_branch)
  2096. wt_porcelain_v2_print_tracking(s);
  2097. for (i = 0; i < s->change.nr; i++) {
  2098. it = &(s->change.items[i]);
  2099. d = it->util;
  2100. if (!d->stagemask)
  2101. wt_porcelain_v2_print_changed_entry(it, s);
  2102. }
  2103. for (i = 0; i < s->change.nr; i++) {
  2104. it = &(s->change.items[i]);
  2105. d = it->util;
  2106. if (d->stagemask)
  2107. wt_porcelain_v2_print_unmerged_entry(it, s);
  2108. }
  2109. for (i = 0; i < s->untracked.nr; i++) {
  2110. it = &(s->untracked.items[i]);
  2111. wt_porcelain_v2_print_other(it, s, '?');
  2112. }
  2113. for (i = 0; i < s->ignored.nr; i++) {
  2114. it = &(s->ignored.items[i]);
  2115. wt_porcelain_v2_print_other(it, s, '!');
  2116. }
  2117. }
  2118. void wt_status_print(struct wt_status *s)
  2119. {
  2120. trace2_data_intmax("status", s->repo, "count/changed", s->change.nr);
  2121. trace2_data_intmax("status", s->repo, "count/untracked",
  2122. s->untracked.nr);
  2123. trace2_data_intmax("status", s->repo, "count/ignored", s->ignored.nr);
  2124. trace2_region_enter("status", "print", s->repo);
  2125. switch (s->status_format) {
  2126. case STATUS_FORMAT_SHORT:
  2127. wt_shortstatus_print(s);
  2128. break;
  2129. case STATUS_FORMAT_PORCELAIN:
  2130. wt_porcelain_print(s);
  2131. break;
  2132. case STATUS_FORMAT_PORCELAIN_V2:
  2133. wt_porcelain_v2_print(s);
  2134. break;
  2135. case STATUS_FORMAT_UNSPECIFIED:
  2136. BUG("finalize_deferred_config() should have been called");
  2137. break;
  2138. case STATUS_FORMAT_NONE:
  2139. case STATUS_FORMAT_LONG:
  2140. wt_longstatus_print(s);
  2141. break;
  2142. }
  2143. trace2_region_leave("status", "print", s->repo);
  2144. }
  2145. /**
  2146. * Returns 1 if there are unstaged changes, 0 otherwise.
  2147. */
  2148. int has_unstaged_changes(struct repository *r, int ignore_submodules)
  2149. {
  2150. struct rev_info rev_info;
  2151. int result;
  2152. repo_init_revisions(r, &rev_info, NULL);
  2153. if (ignore_submodules) {
  2154. rev_info.diffopt.flags.ignore_submodules = 1;
  2155. rev_info.diffopt.flags.override_submodule_config = 1;
  2156. }
  2157. rev_info.diffopt.flags.quick = 1;
  2158. diff_setup_done(&rev_info.diffopt);
  2159. result = run_diff_files(&rev_info, 0);
  2160. return diff_result_code(&rev_info.diffopt, result);
  2161. }
  2162. /**
  2163. * Returns 1 if there are uncommitted changes, 0 otherwise.
  2164. */
  2165. int has_uncommitted_changes(struct repository *r,
  2166. int ignore_submodules)
  2167. {
  2168. struct rev_info rev_info;
  2169. int result;
  2170. if (is_index_unborn(r->index))
  2171. return 0;
  2172. repo_init_revisions(r, &rev_info, NULL);
  2173. if (ignore_submodules)
  2174. rev_info.diffopt.flags.ignore_submodules = 1;
  2175. rev_info.diffopt.flags.quick = 1;
  2176. add_head_to_pending(&rev_info);
  2177. if (!rev_info.pending.nr) {
  2178. /*
  2179. * We have no head (or it's corrupt); use the empty tree,
  2180. * which will complain if the index is non-empty.
  2181. */
  2182. struct tree *tree = lookup_tree(r, the_hash_algo->empty_tree);
  2183. add_pending_object(&rev_info, &tree->object, "");
  2184. }
  2185. diff_setup_done(&rev_info.diffopt);
  2186. result = run_diff_index(&rev_info, 1);
  2187. return diff_result_code(&rev_info.diffopt, result);
  2188. }
  2189. /**
  2190. * If the work tree has unstaged or uncommitted changes, dies with the
  2191. * appropriate message.
  2192. */
  2193. int require_clean_work_tree(struct repository *r,
  2194. const char *action,
  2195. const char *hint,
  2196. int ignore_submodules,
  2197. int gently)
  2198. {
  2199. struct lock_file lock_file = LOCK_INIT;
  2200. int err = 0, fd;
  2201. fd = repo_hold_locked_index(r, &lock_file, 0);
  2202. refresh_index(r->index, REFRESH_QUIET, NULL, NULL, NULL);
  2203. if (0 <= fd)
  2204. repo_update_index_if_able(r, &lock_file);
  2205. rollback_lock_file(&lock_file);
  2206. if (has_unstaged_changes(r, ignore_submodules)) {
  2207. /* TRANSLATORS: the action is e.g. "pull with rebase" */
  2208. error(_("cannot %s: You have unstaged changes."), _(action));
  2209. err = 1;
  2210. }
  2211. if (has_uncommitted_changes(r, ignore_submodules)) {
  2212. if (err)
  2213. error(_("additionally, your index contains uncommitted changes."));
  2214. else
  2215. error(_("cannot %s: Your index contains uncommitted changes."),
  2216. _(action));
  2217. err = 1;
  2218. }
  2219. if (err) {
  2220. if (hint)
  2221. error("%s", hint);
  2222. if (!gently)
  2223. exit(128);
  2224. }
  2225. return err;
  2226. }