From a37ce5cfe1f256b81092dda365b1d66450e0929e Mon Sep 17 00:00:00 2001 From: Thomas Koutcher Date: Thu, 28 Mar 2024 19:00:54 +0100 Subject: [PATCH] Fix parsing of `git ls-tree` for submodules Closes #1282 --- NEWS.adoc | 1 + src/draw.c | 11 +++++------ src/tree.c | 51 +++++++++++++++++++++++++++++++++++---------------- 3 files changed, 41 insertions(+), 22 deletions(-) diff --git a/NEWS.adoc b/NEWS.adoc index 6a8b03c41..9fbc0461f 100644 --- a/NEWS.adoc +++ b/NEWS.adoc @@ -33,6 +33,7 @@ Bug fixes: - Fix status view lockup. - Fix untracked changes and chunk staging behaviour in plain stage view. - Reset state variables when selecting a commit with no reference. + - Fix parsing of `git ls-tree` for submodules. (#1282) tig-2.5.8 --------- diff --git a/src/draw.c b/src/draw.c index a9ded13e6..c2befa472 100644 --- a/src/draw.c +++ b/src/draw.c @@ -276,11 +276,10 @@ draw_id(struct view *view, struct view_column *column, const char *id) } static bool -draw_filename(struct view *view, struct view_column *column, const char *filename, mode_t mode) +draw_filename(struct view *view, struct view_column *column, enum line_type type, const char *filename) { size_t width = filename ? utf8_width(filename) : 0; bool trim = width >= column->width; - enum line_type type = S_ISDIR(mode) ? LINE_DIRECTORY : LINE_FILE; int column_width = column->width ? column->width : width; if (column->opt.file_name.display == FILENAME_NO) @@ -290,9 +289,9 @@ draw_filename(struct view *view, struct view_column *column, const char *filenam } static bool -draw_file_size(struct view *view, struct view_column *column, unsigned long size, mode_t mode) +draw_file_size(struct view *view, struct view_column *column, enum line_type type, unsigned long size) { - const char *str = S_ISDIR(mode) ? NULL : mkfilesize(size, column->opt.file_size.display); + const char *str = type == LINE_FILE ? mkfilesize(size, column->opt.file_size.display) : NULL; if (!column->width || column->opt.file_size.display == FILE_SIZE_NO) return false; @@ -518,7 +517,7 @@ view_column_draw(struct view *view, struct line *line, unsigned int lineno) continue; case VIEW_COLUMN_FILE_SIZE: - if (draw_file_size(view, column, column_data.file_size ? *column_data.file_size : 0, mode)) + if (draw_file_size(view, column, line->type, column_data.file_size ? *column_data.file_size : 0)) return true; continue; @@ -529,7 +528,7 @@ view_column_draw(struct view *view, struct line *line, unsigned int lineno) continue; case VIEW_COLUMN_FILE_NAME: - if (draw_filename(view, column, column_data.file_name, mode)) + if (draw_filename(view, column, line->type, column_data.file_name)) return true; continue; diff --git a/src/tree.c b/src/tree.c index 7dc894d9c..e6c826f1b 100644 --- a/src/tree.c +++ b/src/tree.c @@ -57,15 +57,6 @@ push_tree_stack_entry(struct view *view, const char *name, struct position *posi * 100644 blob 95925677ca47beb0b8cce7c0e0011bcc3f61470f 213045 tig.c */ -#define SIZEOF_TREE_ATTR \ - STRING_SIZE("100644 blob f931e1d229c3e185caad4449bf5b66ed72462657\t") - -#define SIZEOF_TREE_MODE \ - STRING_SIZE("100644 ") - -#define TREE_ID_OFFSET \ - STRING_SIZE("100644 blob ") - #define tree_path_is_parent(path) (!strcmp("..", (path))) struct tree_entry { @@ -222,21 +213,50 @@ tree_read(struct view *view, struct buffer *buf, bool force_stop) struct tree_entry *data; struct line *entry, *line; enum line_type type; + char *pos; + char *mode; + char *id; char *path; size_t size; if (state->read_date || !buf) return tree_read_date(view, buf, state); - if (buf->size <= SIZEOF_TREE_ATTR) - return false; if (view->lines == 0 && !tree_entry(view, LINE_HEADER, view->env->directory, NULL, NULL, 0)) return false; - size = parse_size(buf->data + SIZEOF_TREE_ATTR); - path = strchr(buf->data + SIZEOF_TREE_ATTR, '\t'); - if (!path) + /* 100644 */ + mode = buf->data; + + /* blob */ + pos = strchr(mode, ' '); + if (!pos || !*pos) + return false; + pos++; + if (!strncmp(pos, "blob", STRING_SIZE("blob"))) + type = LINE_FILE; + else if (!strncmp(pos, "tree", STRING_SIZE("tree"))) + type = LINE_DIRECTORY; + else + type = LINE_DEFAULT; + + /* 95925677ca47beb0b8cce7c0e0011bcc3f61470f */ + id = strchr(pos, ' '); + if (!id || !*id) + return false; + id++; + + /* 213045 */ + pos = strchr(id, ' '); + if (!pos || !*pos) + return false; + pos++; + size = parse_size(pos); + + /* tig.c */ + path = strchr(pos, '\t'); + if (!path || !*path) return false; path++; @@ -255,8 +275,7 @@ tree_read(struct view *view, struct buffer *buf, bool force_stop) return false; } - type = buf->data[SIZEOF_TREE_MODE] == 't' ? LINE_DIRECTORY : LINE_FILE; - entry = tree_entry(view, type, path, buf->data, buf->data + TREE_ID_OFFSET, size); + entry = tree_entry(view, type, path, mode, id, size); if (!entry) return false; data = entry->data;