From 4d673c9ad4c65c329a85ebb19c2812ae93183099 Mon Sep 17 00:00:00 2001 From: Elliott Hughes Date: Thu, 28 Jun 2018 16:57:21 -0700 Subject: diff: add timestamps to the ---/+++ lines and --color. (My apologies for mixing these two unrelated changes up.) --- lib/lib.c | 9 ++++++++ lib/lib.h | 1 + tests/diff.test | 8 +++---- toys/other/stat.c | 6 +---- toys/pending/diff.c | 66 ++++++++++++++++++++++++++++++++++++----------------- 5 files changed, 60 insertions(+), 30 deletions(-) diff --git a/lib/lib.c b/lib/lib.c index 41ecb1de..88dd13a0 100644 --- a/lib/lib.c +++ b/lib/lib.c @@ -1394,3 +1394,12 @@ long long millitime(void) clock_gettime(CLOCK_MONOTONIC, &ts); return ts.tv_sec*1000+ts.tv_nsec/1000000; } + +// Formats `ts` in ISO format ("2018-06-28 15:08:58.846386216 -0700"). +char *format_iso_time(char *buf, size_t len, struct timespec *ts) +{ + strftime(buf, len, "%F %T", localtime(&(ts->tv_sec))); + sprintf(buf+strlen(buf), ".%09ld ", ts->tv_nsec); + strftime(buf+strlen(buf), len-strlen(buf), "%z", localtime(&(ts->tv_sec))); + return buf; +} diff --git a/lib/lib.h b/lib/lib.h index 353e262d..61a33fa7 100644 --- a/lib/lib.h +++ b/lib/lib.h @@ -250,6 +250,7 @@ char *getgroupname(gid_t gid); void do_lines(int fd, void (*call)(char **pline, long len)); long environ_bytes(); long long millitime(void); +char *format_iso_time(char *buf, size_t len, struct timespec *ts); #define HR_SPACE 1 // Space between number and units #define HR_B 2 // Use "B" for single byte units diff --git a/tests/diff.test b/tests/diff.test index ca0b682b..ce51f1e8 100755 --- a/tests/diff.test +++ b/tests/diff.test @@ -5,8 +5,8 @@ seq 10 > left seq 11 > right -expected='--- left -+++ right +expected='--- lll ++++ rrr @@ -8,3 +8,4 @@ 8 9 @@ -14,7 +14,7 @@ expected='--- left +11 ' # Hm this only gives unified diffs? -testing "simple" "diff left right" "$expected" "" "" +testing "simple" "diff -L lll -L rrr left right" "$expected" "" "" expected='--- tree1/file @@ -27,4 +27,4 @@ mkdir -p tree1 tree2 echo foo > tree1/file echo food > tree2/file -testing "simple" "diff -r tree1 tree2 |tee out" "$expected" "" "" +testing "simple" "diff -r -L tree1/file -L tree2/file tree1 tree2 |tee out" "$expected" "" "" diff --git a/toys/other/stat.c b/toys/other/stat.c index f68704dd..a1233650 100644 --- a/toys/other/stat.c +++ b/toys/other/stat.c @@ -67,11 +67,7 @@ static void strout(char *val) static void date_stat_format(struct timespec *ts) { - char *s = toybuf+128; - strftime(s, sizeof(toybuf)-128, "%Y-%m-%d %H:%M:%S", - localtime(&(ts->tv_sec))); - sprintf(s+strlen(s), ".%09ld", ts->tv_nsec); - strout(s); + strout(format_iso_time(toybuf+128, sizeof(toybuf)-128, ts)); } static void print_stat(char type) diff --git a/toys/pending/diff.c b/toys/pending/diff.c index b2177c4f..2e0ff926 100644 --- a/toys/pending/diff.c +++ b/toys/pending/diff.c @@ -5,7 +5,7 @@ * * See: http://cm.bell-labs.com/cm/cs/cstr/41.pdf -USE_DIFF(NEWTOY(diff, "<2>2B(ignore-blank-lines)d(minimal)b(ignore-space-change)ut(expand-tabs)w(ignore-all-space)i(ignore-case)T(initial-tab)s(report-identical-files)q(brief)a(text)L(label)*S(starting-file):N(new-file)r(recursive)U(unified)#<0=3", TOYFLAG_USR|TOYFLAG_BIN)) +USE_DIFF(NEWTOY(diff, "<2>2(color)B(ignore-blank-lines)d(minimal)b(ignore-space-change)ut(expand-tabs)w(ignore-all-space)i(ignore-case)T(initial-tab)s(report-identical-files)q(brief)a(text)L(label)*S(starting-file):N(new-file)r(recursive)U(unified)#<0=3", TOYFLAG_USR|TOYFLAG_BIN)) config DIFF bool "diff" @@ -28,6 +28,8 @@ config DIFF -t Expand tabs to spaces in output -U Output LINES lines of context -w Ignore all whitespace + + --color Colored output */ #define FOR_diff @@ -40,6 +42,7 @@ GLOBALS( int dir_num, size, is_binary, status, change, len[2]; int *offset[2]; + struct stat st[2]; ) #define MIN(x,y) ((x) < (y) ? (x) : (y)) @@ -416,6 +419,12 @@ static int *diff(char **files) static void print_diff(int a, int b, char c, int *off_set, FILE *fp) { int i, j, cc, cl; + char *reset = NULL; + + if (c != ' ' && (toys.optflags & FLAG_color)) { + printf("\033[%dm", c == '+' ? 32 : 31); + reset = "\033[0m"; + } for (i = a; i <= b; i++) { fseek(fp, off_set[i - 1], SEEK_SET); @@ -424,7 +433,7 @@ static void print_diff(int a, int b, char c, int *off_set, FILE *fp) for (j = 0, cl = 0; j < (off_set[i] - off_set[i - 1]); j++) { cc = fgetc(fp); if (cc == EOF) { - printf("\n\\ No newline at end of file\n"); + printf("%s\n\\ No newline at end of file\n", reset ? reset : ""); return; } if ((cc == '\t') && (toys.optflags & FLAG_t)) @@ -435,6 +444,7 @@ static void print_diff(int a, int b, char c, int *off_set, FILE *fp) } } } + if (reset) printf(reset); } static char *concat_file_path(char *path, char *default_path) @@ -509,6 +519,14 @@ static int cmp(const void *p1, const void *p2) return strcmp(* (char * const *)p1, * (char * const *)p2); } +static void show_label(char *prefix, char *filename, struct stat *sb) +{ + char date[36]; + + printf("%s %s\t%s\n", prefix, filename, + format_iso_time(date, sizeof(date), &sb->st_mtim)); +} + static void do_diff(char **files) { @@ -564,14 +582,16 @@ static void do_diff(char **files) TT.status = change; //update status, may change bcoz of -w etc. if (!(toys.optflags & FLAG_q) && change) { //start of !FLAG_q - - xprintf("--- %s\n", (toys.optflags & FLAG_L) ? llist->arg : files[0]); - if (((toys.optflags & FLAG_L) && !llist->next) || !(toys.optflags & FLAG_L)) - xprintf("+++ %s\n", files[1]); - else { - while (llist->next) llist = llist->next; - xprintf("+++ %s\n", llist->arg); - } + if (toys.optflags & FLAG_color) printf("\033[1m"); + if (toys.optflags & FLAG_L) printf("--- %s\n", llist->arg); + else show_label("---", files[0], &(TT).st[0]); + if (((toys.optflags & FLAG_L) && !llist->next) || !(toys.optflags & FLAG_L)) + show_label("+++", files[1], &(TT).st[1]); + else { + while (llist->next) llist = llist->next; + printf("+++ %s\n", llist->arg); + } + if (toys.optflags & FLAG_color) printf("\033[0m"); struct diff *t, *ptr1 = d, *ptr2 = d; while (i) { @@ -606,6 +626,7 @@ calc_ct: start2 = MAX(1, ptr1->c - (ptr1->a - ptr1->suff)); end2 = ptr2->prev - ptr2->b + ptr2->d; + if (toys.optflags & FLAG_color) printf("\033[36m"); printf("@@ -%ld", start1 ? ptr1->suff: (ptr1->suff -1)); if (end1 != -1) printf(",%ld ", ptr2->prev-ptr1->suff + 1); else putchar(' '); @@ -613,7 +634,9 @@ calc_ct: printf("+%ld", (end2 - start2 + 1) ? start2: (start2 -1)); if ((end2 - start2 +1) != 1) printf(",%ld ", (end2 - start2 +1)); else putchar(' '); - printf("@@\n"); + printf("@@"); + if (toys.optflags & FLAG_color) printf("\033[0m"); + putchar('\n'); for (t = ptr1; t <= ptr2; t++) { if (t== ptr1) print_diff(t->suff, t->a-1, ' ', TT.offset[0], file[0].fp); @@ -765,17 +788,18 @@ static void diff_dir(int *start) void diff_main(void) { - struct stat st[2]; int j = 0, k = 1, start[2] = {1, 1}; char *files[2]; + if ((toys.optflags & FLAG_color) && !isatty(1)) toys.optflags ^= FLAG_color; + for (j = 0; j < 2; j++) { files[j] = toys.optargs[j]; if (IS_STDIN(files[j])) { - if (fstat(0, &st[j]) == -1) + if (fstat(0, &TT.st[j]) == -1) perror_exit("can fstat %s", files[j]); } else { - if (stat(files[j], &st[j]) == -1) + if (stat(files[j], &TT.st[j]) == -1) perror_exit("can't stat %s", files[j]); } } @@ -786,16 +810,16 @@ void diff_main(void) } if ((IS_STDIN(files[0]) || IS_STDIN(files[1])) - && (S_ISDIR(st[0].st_mode) || S_ISDIR(st[1].st_mode))) + && (S_ISDIR(TT.st[0].st_mode) || S_ISDIR(TT.st[1].st_mode))) error_exit("can't compare stdin to directory"); - if ((st[0].st_ino == st[1].st_ino) //physicaly same device - &&(st[0].st_dev == st[1].st_dev)) { + if ((TT.st[0].st_ino == TT.st[1].st_ino) //physicaly same device + && (TT.st[0].st_dev == TT.st[1].st_dev)) { show_status(files); return ; } - if (S_ISDIR(st[0].st_mode) && S_ISDIR(st[1].st_mode)) { + if (S_ISDIR(TT.st[0].st_mode) && S_ISDIR(TT.st[1].st_mode)) { for (j = 0; j < 2; j++) { memset(&dir[j], 0, sizeof(struct dir_t)); dirtree_flagread(files[j], DIRTREE_SYMFOLLOW, list_dir); @@ -820,12 +844,12 @@ void diff_main(void) free(dir[0].list); //free array free(dir[1].list); } else { - if (S_ISDIR(st[0].st_mode) || S_ISDIR(st[1].st_mode)) { - int d = S_ISDIR(st[0].st_mode); + if (S_ISDIR(TT.st[0].st_mode) || S_ISDIR(TT.st[1].st_mode)) { + int d = S_ISDIR(TT.st[0].st_mode); char *slash = strrchr(files[d], '/'); files[1 - d] = concat_file_path(files[1 - d], slash ? slash + 1 : files[d]); - if ((stat(files[1 - d], &st[1 - d])) == -1) + if ((stat(files[1 - d], &TT.st[1 - d])) == -1) perror_exit("%s", files[1 - d]); } do_diff(files); -- cgit v1.2.3