summaryrefslogtreecommitdiffstats
path: root/examples/ls-files.c
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--examples/ls-files.c131
1 files changed, 131 insertions, 0 deletions
diff --git a/examples/ls-files.c b/examples/ls-files.c
new file mode 100644
index 0000000..a235069
--- /dev/null
+++ b/examples/ls-files.c
@@ -0,0 +1,131 @@
+/*
+ * libgit2 "ls-files" example - shows how to view all files currently in the index
+ *
+ * Written by the libgit2 contributors
+ *
+ * To the extent possible under law, the author(s) have dedicated all copyright
+ * and related and neighboring rights to this software to the public domain
+ * worldwide. This software is distributed without any warranty.
+ *
+ * You should have received a copy of the CC0 Public Domain Dedication along
+ * with this software. If not, see
+ * <http://creativecommons.org/publicdomain/zero/1.0/>.
+ */
+
+#include "common.h"
+
+/**
+ * This example demonstrates the libgit2 index APIs to roughly
+ * simulate the output of `git ls-files`.
+ * `git ls-files` has many options and this currently does not show them.
+ *
+ * `git ls-files` base command shows all paths in the index at that time.
+ * This includes staged and committed files, but unstaged files will not display.
+ *
+ * This currently supports the default behavior and the `--error-unmatch` option.
+ */
+
+struct ls_options {
+ int error_unmatch;
+ char *files[1024];
+ size_t file_count;
+};
+
+static void usage(const char *message, const char *arg)
+{
+ if (message && arg)
+ fprintf(stderr, "%s: %s\n", message, arg);
+ else if (message)
+ fprintf(stderr, "%s\n", message);
+ fprintf(stderr, "usage: ls-files [--error-unmatch] [--] [<file>...]\n");
+ exit(1);
+}
+
+static int parse_options(struct ls_options *opts, int argc, char *argv[])
+{
+ int parsing_files = 0;
+ int i;
+
+ memset(opts, 0, sizeof(struct ls_options));
+
+ if (argc < 2)
+ return 0;
+
+ for (i = 1; i < argc; ++i) {
+ char *a = argv[i];
+
+ /* if it doesn't start with a '-' or is after the '--' then it is a file */
+ if (a[0] != '-' || parsing_files) {
+ parsing_files = 1;
+
+ /* watch for overflows (just in case) */
+ if (opts->file_count == 1024) {
+ fprintf(stderr, "ls-files can only support 1024 files at this time.\n");
+ return -1;
+ }
+
+ opts->files[opts->file_count++] = a;
+ } else if (!strcmp(a, "--")) {
+ parsing_files = 1;
+ } else if (!strcmp(a, "--error-unmatch")) {
+ opts->error_unmatch = 1;
+ } else {
+ usage("Unsupported argument", a);
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
+static int print_paths(struct ls_options *opts, git_index *index)
+{
+ size_t i;
+ const git_index_entry *entry;
+
+ /* if there are no files explicitly listed by the user print all entries in the index */
+ if (opts->file_count == 0) {
+ size_t entry_count = git_index_entrycount(index);
+
+ for (i = 0; i < entry_count; i++) {
+ entry = git_index_get_byindex(index, i);
+ puts(entry->path);
+ }
+ return 0;
+ }
+
+ /* loop through the files found in the args and print them if they exist */
+ for (i = 0; i < opts->file_count; ++i) {
+ const char *path = opts->files[i];
+
+ if ((entry = git_index_get_bypath(index, path, GIT_INDEX_STAGE_NORMAL)) != NULL) {
+ puts(path);
+ } else if (opts->error_unmatch) {
+ fprintf(stderr, "error: pathspec '%s' did not match any file(s) known to git.\n", path);
+ fprintf(stderr, "Did you forget to 'git add'?\n");
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
+int lg2_ls_files(git_repository *repo, int argc, char *argv[])
+{
+ git_index *index = NULL;
+ struct ls_options opts;
+ int error;
+
+ if ((error = parse_options(&opts, argc, argv)) < 0)
+ return error;
+
+ if ((error = git_repository_index(&index, repo)) < 0)
+ goto cleanup;
+
+ error = print_paths(&opts, index);
+
+cleanup:
+ git_index_free(index);
+
+ return error;
+}