commit - 80bd227c8266b1bdccfbaca37c2d9366e6e9ef67
commit + c1669e2e5fb4f6007afe46318e82a4e0de689390
blob - b85c7d4acf1dfb346061b17df8a3b3ba58d863cc
blob + 5e8952c6e1329f6cee0405f65332a159c2395f7b
--- got/got.1
+++ got/got.1
If not specified, assume the repository is located at or above the current
working directory.
.El
-.It Cm tree [ Fl c Ar commit ] [ Fl r Ar repository-path ] [ Fl i ] [ Ar path ]
+.It Cm tree [ Fl c Ar commit ] [ Fl r Ar repository-path ] [ Fl i ] [ Fl R] [ Ar path ]
Display a listing of files and directories at the specified
directory path in the repository.
If no path is specified, the root directory is listed.
working directory.
.It Fl i
Show object IDs of files (blob objects) and directories (tree objects).
+.It Fl R
+Recurse into sub-directories.
.El
.Sh EXIT STATUS
.Ex -std got
blob - bb5861b87334a06680c1f45a5291002db4e8204f
blob + 9344bf93767b2a5453c8f923e3ee059ef601e562
--- got/got.c
+++ got/got.c
__dead static void
usage_tree(void)
{
- fprintf(stderr, "usage: %s tree [-c commit] [-r repository-path] [-i] path\n",
+ fprintf(stderr,
+ "usage: %s tree [-c commit] [-r repository-path] [-iR] path\n",
getprogname());
exit(1);
}
+static void
+print_entry(struct got_tree_entry *te, const char *id, const char *path,
+ const char *root_path)
+{
+ int is_root_path = (strcmp(path, root_path) == 0);
+ path += strlen(root_path);
+ while (path[0] == '/')
+ path++;
+
+ printf("%s%s%s%s%s\n", id ? id : "", path,
+ is_root_path ? "" : "/",
+ te->name, S_ISDIR(te->mode) ? "/" : "");
+}
+
static const struct got_error *
print_tree(const char *path, struct got_object_id *commit_id,
- int show_ids, struct got_repository *repo)
+ int show_ids, int recurse, const char *root_path,
+ struct got_repository *repo)
{
const struct got_error *err = NULL;
struct got_object_id *tree_id = NULL;
}
free(id_str);
}
- printf("%s%s%s\n", id ? id : "",
- te->name, S_ISDIR(te->mode) ? "/" : "");
- te = SIMPLEQ_NEXT(te, entry);
+ print_entry(te, id, path, root_path);
free(id);
+
+ if (recurse && S_ISDIR(te->mode)) {
+ char *child_path;
+ if (asprintf(&child_path, "%s%s%s", path,
+ path[0] == '/' && path[1] == '\0' ? "" : "/",
+ te->name) == -1) {
+ err = got_error_from_errno();
+ goto done;
+ }
+ err = print_tree(child_path, commit_id, show_ids, 1,
+ root_path, repo);
+ free(child_path);
+ if (err)
+ goto done;
+ }
+
+ te = SIMPLEQ_NEXT(te, entry);
}
done:
if (tree)
char *path, *cwd = NULL, *repo_path = NULL, *in_repo_path = NULL;
struct got_object_id *commit_id = NULL;
char *commit_id_str = NULL;
- int show_ids = 0;
+ int show_ids = 0, recurse = 0;
int ch;
#ifndef PROFILE
err(1, "pledge");
#endif
- while ((ch = getopt(argc, argv, "c:r:i")) != -1) {
+ while ((ch = getopt(argc, argv, "c:r:iR")) != -1) {
switch (ch) {
case 'c':
commit_id_str = optarg;
case 'i':
show_ids = 1;
break;
+ case 'R':
+ recurse = 1;
+ break;
default:
usage();
/* NOTREACHED */
goto done;
}
- error = print_tree(in_repo_path, commit_id, show_ids, repo);
+ error = print_tree(in_repo_path, commit_id, show_ids, recurse,
+ in_repo_path, repo);
done:
free(in_repo_path);
free(repo_path);