diff options
Diffstat (limited to 'builtin/ls-files.c')
-rw-r--r-- | builtin/ls-files.c | 263 |
1 files changed, 69 insertions, 194 deletions
diff --git a/builtin/ls-files.c b/builtin/ls-files.c index 625f48f0d6..a0229c3277 100644 --- a/builtin/ls-files.c +++ b/builtin/ls-files.c @@ -5,13 +5,12 @@ * * Copyright (C) Linus Torvalds, 2005 */ -#include "cache.h" +#include "builtin.h" #include "repository.h" #include "config.h" #include "convert.h" #include "quote.h" #include "dir.h" -#include "builtin.h" #include "gettext.h" #include "object-name.h" #include "strbuf.h" @@ -20,11 +19,17 @@ #include "parse-options.h" #include "resolve-undo.h" #include "string-list.h" +#include "path.h" #include "pathspec.h" +#include "read-cache.h" #include "run-command.h" #include "setup.h" +#include "sparse-index.h" #include "submodule.h" #include "submodule-config.h" +#include "object-store.h" +#include "hex.h" + static int abbrev; static int show_deleted; @@ -241,68 +246,75 @@ static void show_submodule(struct repository *superproject, repo_clear(&subrepo); } -struct show_index_data { - const char *pathname; - struct index_state *istate; - const struct cache_entry *ce; -}; - -static size_t expand_show_index(struct strbuf *sb, const char *start, - void *context) +static void expand_objectsize(struct strbuf *line, const struct object_id *oid, + const enum object_type type, unsigned int padded) { - struct show_index_data *data = context; - const char *end; - const char *p; - size_t len = strbuf_expand_literal_cb(sb, start, NULL); - struct stat st; - - if (len) - return len; - if (*start != '(') - die(_("bad ls-files format: element '%s' " - "does not start with '('"), start); - - end = strchr(start + 1, ')'); - if (!end) - die(_("bad ls-files format: element '%s' " - "does not end in ')'"), start); - - len = end - start + 1; - if (skip_prefix(start, "(objectmode)", &p)) - strbuf_addf(sb, "%06o", data->ce->ce_mode); - else if (skip_prefix(start, "(objectname)", &p)) - strbuf_add_unique_abbrev(sb, &data->ce->oid, abbrev); - else if (skip_prefix(start, "(stage)", &p)) - strbuf_addf(sb, "%d", ce_stage(data->ce)); - else if (skip_prefix(start, "(eolinfo:index)", &p)) - strbuf_addstr(sb, S_ISREG(data->ce->ce_mode) ? - get_cached_convert_stats_ascii(data->istate, - data->ce->name) : ""); - else if (skip_prefix(start, "(eolinfo:worktree)", &p)) - strbuf_addstr(sb, !lstat(data->pathname, &st) && - S_ISREG(st.st_mode) ? - get_wt_convert_stats_ascii(data->pathname) : ""); - else if (skip_prefix(start, "(eolattr)", &p)) - strbuf_addstr(sb, get_convert_attr_ascii(data->istate, - data->pathname)); - else if (skip_prefix(start, "(path)", &p)) - write_name_to_buf(sb, data->pathname); - else - die(_("bad ls-files format: %%%.*s"), (int)len, start); - - return len; + if (type == OBJ_BLOB) { + unsigned long size; + if (oid_object_info(the_repository, oid, &size) < 0) + die(_("could not get object info about '%s'"), + oid_to_hex(oid)); + if (padded) + strbuf_addf(line, "%7"PRIuMAX, (uintmax_t)size); + else + strbuf_addf(line, "%"PRIuMAX, (uintmax_t)size); + } else if (padded) { + strbuf_addf(line, "%7s", "-"); + } else { + strbuf_addstr(line, "-"); + } } static void show_ce_fmt(struct repository *repo, const struct cache_entry *ce, const char *format, const char *fullname) { - struct show_index_data data = { - .pathname = fullname, - .istate = repo->index, - .ce = ce, - }; struct strbuf sb = STRBUF_INIT; - strbuf_expand(&sb, format, expand_show_index, &data); + while (strbuf_expand_step(&sb, &format)) { + const char *end; + size_t len; + struct stat st; + + if (skip_prefix(format, "%", &format)) + strbuf_addch(&sb, '%'); + else if ((len = strbuf_expand_literal(&sb, format))) + format += len; + else if (*format != '(') + die(_("bad ls-files format: element '%s' " + "does not start with '('"), format); + else if (!(end = strchr(format + 1, ')'))) + die(_("bad ls-files format: element '%s' " + "does not end in ')'"), format); + else if (skip_prefix(format, "(objectmode)", &format)) + strbuf_addf(&sb, "%06o", ce->ce_mode); + else if (skip_prefix(format, "(objectname)", &format)) + strbuf_add_unique_abbrev(&sb, &ce->oid, abbrev); + else if (skip_prefix(format, "(objecttype)", &format)) + strbuf_addstr(&sb, type_name(object_type(ce->ce_mode))); + else if (skip_prefix(format, "(objectsize:padded)", &format)) + expand_objectsize(&sb, &ce->oid, + object_type(ce->ce_mode), 1); + else if (skip_prefix(format, "(objectsize)", &format)) + expand_objectsize(&sb, &ce->oid, + object_type(ce->ce_mode), 0); + else if (skip_prefix(format, "(stage)", &format)) + strbuf_addf(&sb, "%d", ce_stage(ce)); + else if (skip_prefix(format, "(eolinfo:index)", &format)) + strbuf_addstr(&sb, S_ISREG(ce->ce_mode) ? + get_cached_convert_stats_ascii(repo->index, + ce->name) : ""); + else if (skip_prefix(format, "(eolinfo:worktree)", &format)) + strbuf_addstr(&sb, !lstat(fullname, &st) && + S_ISREG(st.st_mode) ? + get_wt_convert_stats_ascii(fullname) : ""); + else if (skip_prefix(format, "(eolattr)", &format)) + strbuf_addstr(&sb, get_convert_attr_ascii(repo->index, + fullname)); + else if (skip_prefix(format, "(path)", &format)) + write_name_to_buf(&sb, fullname); + else + die(_("bad ls-files format: %%%.*s"), + (int)(end - format + 1), format); + } strbuf_addch(&sb, line_terminator); fwrite(sb.buf, sb.len, 1, stdout); strbuf_release(&sb); @@ -516,143 +528,6 @@ static int get_common_prefix_len(const char *common_prefix) return common_prefix_len; } -static int read_one_entry_opt(struct index_state *istate, - const struct object_id *oid, - struct strbuf *base, - const char *pathname, - unsigned mode, int opt) -{ - int len; - struct cache_entry *ce; - - if (S_ISDIR(mode)) - return READ_TREE_RECURSIVE; - - len = strlen(pathname); - ce = make_empty_cache_entry(istate, base->len + len); - - ce->ce_mode = create_ce_mode(mode); - ce->ce_flags = create_ce_flags(1); - ce->ce_namelen = base->len + len; - memcpy(ce->name, base->buf, base->len); - memcpy(ce->name + base->len, pathname, len+1); - oidcpy(&ce->oid, oid); - return add_index_entry(istate, ce, opt); -} - -static int read_one_entry(const struct object_id *oid, struct strbuf *base, - const char *pathname, unsigned mode, - void *context) -{ - struct index_state *istate = context; - return read_one_entry_opt(istate, oid, base, pathname, - mode, - ADD_CACHE_OK_TO_ADD|ADD_CACHE_SKIP_DFCHECK); -} - -/* - * This is used when the caller knows there is no existing entries at - * the stage that will conflict with the entry being added. - */ -static int read_one_entry_quick(const struct object_id *oid, struct strbuf *base, - const char *pathname, unsigned mode, - void *context) -{ - struct index_state *istate = context; - return read_one_entry_opt(istate, oid, base, pathname, - mode, ADD_CACHE_JUST_APPEND); -} - -/* - * Read the tree specified with --with-tree option - * (typically, HEAD) into stage #1 and then - * squash them down to stage #0. This is used for - * --error-unmatch to list and check the path patterns - * that were given from the command line. We are not - * going to write this index out. - */ -void overlay_tree_on_index(struct index_state *istate, - const char *tree_name, const char *prefix) -{ - struct tree *tree; - struct object_id oid; - struct pathspec pathspec; - struct cache_entry *last_stage0 = NULL; - int i; - read_tree_fn_t fn = NULL; - int err; - - if (repo_get_oid(the_repository, tree_name, &oid)) - die("tree-ish %s not found.", tree_name); - tree = parse_tree_indirect(&oid); - if (!tree) - die("bad tree-ish %s", tree_name); - - /* Hoist the unmerged entries up to stage #3 to make room */ - /* TODO: audit for interaction with sparse-index. */ - ensure_full_index(istate); - for (i = 0; i < istate->cache_nr; i++) { - struct cache_entry *ce = istate->cache[i]; - if (!ce_stage(ce)) - continue; - ce->ce_flags |= CE_STAGEMASK; - } - - if (prefix) { - static const char *(matchbuf[1]); - matchbuf[0] = NULL; - parse_pathspec(&pathspec, PATHSPEC_ALL_MAGIC, - PATHSPEC_PREFER_CWD, prefix, matchbuf); - } else - memset(&pathspec, 0, sizeof(pathspec)); - - /* - * See if we have cache entry at the stage. If so, - * do it the original slow way, otherwise, append and then - * sort at the end. - */ - for (i = 0; !fn && i < istate->cache_nr; i++) { - const struct cache_entry *ce = istate->cache[i]; - if (ce_stage(ce) == 1) - fn = read_one_entry; - } - - if (!fn) - fn = read_one_entry_quick; - err = read_tree(the_repository, tree, &pathspec, fn, istate); - clear_pathspec(&pathspec); - if (err) - die("unable to read tree entries %s", tree_name); - - /* - * Sort the cache entry -- we need to nuke the cache tree, though. - */ - if (fn == read_one_entry_quick) { - cache_tree_free(&istate->cache_tree); - QSORT(istate->cache, istate->cache_nr, cmp_cache_name_compare); - } - - for (i = 0; i < istate->cache_nr; i++) { - struct cache_entry *ce = istate->cache[i]; - switch (ce_stage(ce)) { - case 0: - last_stage0 = ce; - /* fallthru */ - default: - continue; - case 1: - /* - * If there is stage #0 entry for this, we do not - * need to show it. We use CE_UPDATE bit to mark - * such an entry. - */ - if (last_stage0 && - !strcmp(last_stage0->name, ce->name)) - ce->ce_flags |= CE_UPDATE; - } - } -} - static const char * const ls_files_usage[] = { N_("git ls-files [<options>] [<file>...]"), NULL |