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.

240 lines
5.4KB

  1. #include "cache.h"
  2. #include "color.h"
  3. #include "config.h"
  4. #include "sideband.h"
  5. #include "help.h"
  6. struct keyword_entry {
  7. /*
  8. * We use keyword as config key so it should be a single alphanumeric word.
  9. */
  10. const char *keyword;
  11. char color[COLOR_MAXLEN];
  12. };
  13. static struct keyword_entry keywords[] = {
  14. { "hint", GIT_COLOR_YELLOW },
  15. { "warning", GIT_COLOR_BOLD_YELLOW },
  16. { "success", GIT_COLOR_BOLD_GREEN },
  17. { "error", GIT_COLOR_BOLD_RED },
  18. };
  19. /* Returns a color setting (GIT_COLOR_NEVER, etc). */
  20. static int use_sideband_colors(void)
  21. {
  22. static int use_sideband_colors_cached = -1;
  23. const char *key = "color.remote";
  24. struct strbuf sb = STRBUF_INIT;
  25. char *value;
  26. int i;
  27. if (use_sideband_colors_cached >= 0)
  28. return use_sideband_colors_cached;
  29. if (!git_config_get_string(key, &value)) {
  30. use_sideband_colors_cached = git_config_colorbool(key, value);
  31. } else if (!git_config_get_string("color.ui", &value)) {
  32. use_sideband_colors_cached = git_config_colorbool("color.ui", value);
  33. } else {
  34. use_sideband_colors_cached = GIT_COLOR_AUTO;
  35. }
  36. for (i = 0; i < ARRAY_SIZE(keywords); i++) {
  37. strbuf_reset(&sb);
  38. strbuf_addf(&sb, "%s.%s", key, keywords[i].keyword);
  39. if (git_config_get_string(sb.buf, &value))
  40. continue;
  41. if (color_parse(value, keywords[i].color))
  42. continue;
  43. }
  44. strbuf_release(&sb);
  45. return use_sideband_colors_cached;
  46. }
  47. void list_config_color_sideband_slots(struct string_list *list, const char *prefix)
  48. {
  49. int i;
  50. for (i = 0; i < ARRAY_SIZE(keywords); i++)
  51. list_config_item(list, prefix, keywords[i].keyword);
  52. }
  53. /*
  54. * Optionally highlight one keyword in remote output if it appears at the start
  55. * of the line. This should be called for a single line only, which is
  56. * passed as the first N characters of the SRC array.
  57. *
  58. * NEEDSWORK: use "size_t n" instead for clarity.
  59. */
  60. static void maybe_colorize_sideband(struct strbuf *dest, const char *src, int n)
  61. {
  62. int i;
  63. if (!want_color_stderr(use_sideband_colors())) {
  64. strbuf_add(dest, src, n);
  65. return;
  66. }
  67. while (0 < n && isspace(*src)) {
  68. strbuf_addch(dest, *src);
  69. src++;
  70. n--;
  71. }
  72. for (i = 0; i < ARRAY_SIZE(keywords); i++) {
  73. struct keyword_entry *p = keywords + i;
  74. int len = strlen(p->keyword);
  75. if (n < len)
  76. continue;
  77. /*
  78. * Match case insensitively, so we colorize output from existing
  79. * servers regardless of the case that they use for their
  80. * messages. We only highlight the word precisely, so
  81. * "successful" stays uncolored.
  82. */
  83. if (!strncasecmp(p->keyword, src, len) &&
  84. (len == n || !isalnum(src[len]))) {
  85. strbuf_addstr(dest, p->color);
  86. strbuf_add(dest, src, len);
  87. strbuf_addstr(dest, GIT_COLOR_RESET);
  88. n -= len;
  89. src += len;
  90. break;
  91. }
  92. }
  93. strbuf_add(dest, src, n);
  94. }
  95. #define DISPLAY_PREFIX "remote: "
  96. #define ANSI_SUFFIX "\033[K"
  97. #define DUMB_SUFFIX " "
  98. int demultiplex_sideband(const char *me, char *buf, int len,
  99. int die_on_error,
  100. struct strbuf *scratch,
  101. enum sideband_type *sideband_type)
  102. {
  103. static const char *suffix;
  104. const char *b, *brk;
  105. int band;
  106. if (!suffix) {
  107. if (isatty(2) && !is_terminal_dumb())
  108. suffix = ANSI_SUFFIX;
  109. else
  110. suffix = DUMB_SUFFIX;
  111. }
  112. if (len == 0) {
  113. *sideband_type = SIDEBAND_FLUSH;
  114. goto cleanup;
  115. }
  116. if (len < 1) {
  117. strbuf_addf(scratch,
  118. "%s%s: protocol error: no band designator",
  119. scratch->len ? "\n" : "", me);
  120. *sideband_type = SIDEBAND_PROTOCOL_ERROR;
  121. goto cleanup;
  122. }
  123. band = buf[0] & 0xff;
  124. buf[len] = '\0';
  125. len--;
  126. switch (band) {
  127. case 3:
  128. if (die_on_error)
  129. die("remote error: %s", buf + 1);
  130. strbuf_addf(scratch, "%s%s", scratch->len ? "\n" : "",
  131. DISPLAY_PREFIX);
  132. maybe_colorize_sideband(scratch, buf + 1, len);
  133. *sideband_type = SIDEBAND_REMOTE_ERROR;
  134. break;
  135. case 2:
  136. b = buf + 1;
  137. /*
  138. * Append a suffix to each nonempty line to clear the
  139. * end of the screen line.
  140. *
  141. * The output is accumulated in a buffer and
  142. * each line is printed to stderr using
  143. * write(2) to ensure inter-process atomicity.
  144. */
  145. while ((brk = strpbrk(b, "\n\r"))) {
  146. int linelen = brk - b;
  147. if (!scratch->len)
  148. strbuf_addstr(scratch, DISPLAY_PREFIX);
  149. if (linelen > 0) {
  150. maybe_colorize_sideband(scratch, b, linelen);
  151. strbuf_addstr(scratch, suffix);
  152. }
  153. strbuf_addch(scratch, *brk);
  154. xwrite(2, scratch->buf, scratch->len);
  155. strbuf_reset(scratch);
  156. b = brk + 1;
  157. }
  158. if (*b) {
  159. strbuf_addstr(scratch, scratch->len ?
  160. "" : DISPLAY_PREFIX);
  161. maybe_colorize_sideband(scratch, b, strlen(b));
  162. }
  163. return 0;
  164. case 1:
  165. *sideband_type = SIDEBAND_PRIMARY;
  166. break;
  167. default:
  168. strbuf_addf(scratch, "%s%s: protocol error: bad band #%d",
  169. scratch->len ? "\n" : "", me, band);
  170. *sideband_type = SIDEBAND_PROTOCOL_ERROR;
  171. break;
  172. }
  173. cleanup:
  174. if (die_on_error && *sideband_type == SIDEBAND_PROTOCOL_ERROR)
  175. die("%s", scratch->buf);
  176. if (scratch->len) {
  177. strbuf_addch(scratch, '\n');
  178. xwrite(2, scratch->buf, scratch->len);
  179. }
  180. strbuf_release(scratch);
  181. return 1;
  182. }
  183. /*
  184. * fd is connected to the remote side; send the sideband data
  185. * over multiplexed packet stream.
  186. */
  187. void send_sideband(int fd, int band, const char *data, ssize_t sz, int packet_max)
  188. {
  189. const char *p = data;
  190. while (sz) {
  191. unsigned n;
  192. char hdr[5];
  193. n = sz;
  194. if (packet_max - 5 < n)
  195. n = packet_max - 5;
  196. if (0 <= band) {
  197. xsnprintf(hdr, sizeof(hdr), "%04x", n + 5);
  198. hdr[4] = band;
  199. write_or_die(fd, hdr, 5);
  200. } else {
  201. xsnprintf(hdr, sizeof(hdr), "%04x", n + 4);
  202. write_or_die(fd, hdr, 4);
  203. }
  204. write_or_die(fd, p, n);
  205. p += n;
  206. sz -= n;
  207. }
  208. }