|
| 1 | +/* |
| 2 | + * libgit2 "ls-files" example - shows how to view all files currently in the index |
| 3 | + * |
| 4 | + * Written by the libgit2 contributors |
| 5 | + * |
| 6 | + * To the extent possible under law, the author(s) have dedicated all copyright |
| 7 | + * and related and neighboring rights to this software to the public domain |
| 8 | + * worldwide. This software is distributed without any warranty. |
| 9 | + * |
| 10 | + * You should have received a copy of the CC0 Public Domain Dedication along |
| 11 | + * with this software. If not, see |
| 12 | + * <http://creativecommons.org/publicdomain/zero/1.0/>. |
| 13 | + */ |
| 14 | + |
| 15 | +#include "common.h" |
| 16 | +#include "array.h" |
| 17 | + |
| 18 | +/** |
| 19 | + * This example demonstrates the libgit2 index APIs to roughly |
| 20 | + * simulate the output of `git ls-files`. |
| 21 | + * `git ls-files` has many options and this currently does not show them. |
| 22 | + * |
| 23 | + * `git ls-files` base command shows all paths in the index at that time. |
| 24 | + * This includes staged and committed files, but unstaged files will not display. |
| 25 | + * |
| 26 | + * This currently supports the default behavior and the `--error-unmatch` option. |
| 27 | + */ |
| 28 | + |
| 29 | +typedef struct { |
| 30 | + int error_unmatch; |
| 31 | + char *files[1024]; |
| 32 | + size_t file_count; |
| 33 | +} ls_options; |
| 34 | + |
| 35 | +static void usage(const char *message, const char *arg) |
| 36 | +{ |
| 37 | + if (message && arg) |
| 38 | + fprintf(stderr, "%s: %s\n", message, arg); |
| 39 | + else if (message) |
| 40 | + fprintf(stderr, "%s\n", message); |
| 41 | + fprintf(stderr, "usage: ls-files [--error-unmatch] [--] [<file>...]\n"); |
| 42 | + exit(1); |
| 43 | +} |
| 44 | + |
| 45 | +static int parse_options(ls_options *opts, int argc, char *argv[]) |
| 46 | +{ |
| 47 | + int parsing_files = 0; |
| 48 | + int i; |
| 49 | + |
| 50 | + memset(opts, 0, sizeof(ls_options)); |
| 51 | + |
| 52 | + if (argc < 2) |
| 53 | + return 0; |
| 54 | + |
| 55 | + for (i = 1; i < argc; ++i) { |
| 56 | + char *a = argv[i]; |
| 57 | + |
| 58 | + /* if it doesn't start with a '-' or is after the '--' then it is a file */ |
| 59 | + if (a[0] != '-' || parsing_files) { |
| 60 | + parsing_files = 1; |
| 61 | + |
| 62 | + /* watch for overflows (just in case) */ |
| 63 | + if (opts->file_count == 1024) { |
| 64 | + fprintf(stderr, "ls-files can only support 1024 files at this time.\n"); |
| 65 | + return -1; |
| 66 | + } |
| 67 | + |
| 68 | + opts->files[opts->file_count++] = a; |
| 69 | + } else if (!strcmp(a, "--")) { |
| 70 | + parsing_files = 1; |
| 71 | + } else if (!strcmp(a, "--error-unmatch")) { |
| 72 | + opts->error_unmatch = 1; |
| 73 | + } else { |
| 74 | + usage("Unsupported argument", a); |
| 75 | + return -1; |
| 76 | + } |
| 77 | + } |
| 78 | + |
| 79 | + return 0; |
| 80 | +} |
| 81 | + |
| 82 | +static int print_paths(ls_options *opts, git_index *index) |
| 83 | +{ |
| 84 | + size_t i; |
| 85 | + const git_index_entry *entry; |
| 86 | + |
| 87 | + /* if there are no files explicitly listed by the user print all entries in the index */ |
| 88 | + if (opts->file_count == 0) { |
| 89 | + size_t entry_count = git_index_entrycount(index); |
| 90 | + |
| 91 | + for (i = 0; i < entry_count; i++) { |
| 92 | + entry = git_index_get_byindex(index, i); |
| 93 | + puts(entry->path); |
| 94 | + } |
| 95 | + return 0; |
| 96 | + } |
| 97 | + |
| 98 | + /* loop through the files found in the args and print them if they exist */ |
| 99 | + for (i = 0; i < opts->file_count; ++i) { |
| 100 | + const char *path = opts->files[i]; |
| 101 | + |
| 102 | + if ((entry = git_index_get_bypath(index, path, GIT_INDEX_STAGE_NORMAL)) != NULL) { |
| 103 | + puts(path); |
| 104 | + } else if (opts->error_unmatch) { |
| 105 | + fprintf(stderr, "error: pathspec '%s' did not match any file(s) known to git.\n", path); |
| 106 | + fprintf(stderr, "Did you forget to 'git add'?\n"); |
| 107 | + return -1; |
| 108 | + } |
| 109 | + } |
| 110 | + |
| 111 | + return 0; |
| 112 | +} |
| 113 | + |
| 114 | +int main(int argc, char *argv[]) |
| 115 | +{ |
| 116 | + ls_options opts; |
| 117 | + git_repository *repo = NULL; |
| 118 | + git_index *index = NULL; |
| 119 | + int error; |
| 120 | + |
| 121 | + if ((error = parse_options(&opts, argc, argv)) < 0) |
| 122 | + return error; |
| 123 | + |
| 124 | + git_libgit2_init(); |
| 125 | + |
| 126 | + if ((error = git_repository_open_ext(&repo, ".", 0, NULL)) < 0) |
| 127 | + goto cleanup; |
| 128 | + |
| 129 | + if ((error = git_repository_index(&index, repo)) < 0) |
| 130 | + goto cleanup; |
| 131 | + |
| 132 | + error = print_paths(&opts, index); |
| 133 | + |
| 134 | +cleanup: |
| 135 | + git_index_free(index); |
| 136 | + git_repository_free(repo); |
| 137 | + git_libgit2_shutdown(); |
| 138 | + |
| 139 | + return error; |
| 140 | +} |
0 commit comments