[prev in list] [next in list] [prev in thread] [next in thread]
List: gameoftrees
Subject: make got/tog tree show symlink targets
From: Stefan Sperling <stsp () stsp ! name>
Date: 2020-05-17 10:41:08
Message-ID: 20200517104108.GD91819 () ted ! stsp ! name
[Download RAW message or body]
This patch makes symlink target paths show up in the output of 'got tree'
and also makes them visible in the 'tog tree' view.
The new output looks like 'ls -lF': link@ -> target
Beforehand, symbolic links were shown like this: link@
While symlinks aren't actually supported yet, at least we can now see
where they point to. This makes browsing repositories which contain
symlinks a bit easier.
Ok?
diff 5d58be1291225e7e6b5febddb818535c9907fd09 /home/stsp/src/got
blob - 37523a3f4cb248caf256b0e5a47510f04058befc
file + got/got.1
--- got/got.1
+++ got/got.1
@@ -843,6 +843,8 @@ annotations:
.It $ Ta entry is a Git submodule
.El
.Pp
+Symbolic link entries are also annotated with the target path of the link.
+.Pp
If no
.Ar path
is specified, list the repository path corresponding to the current
blob - e8ed8348332436dcca1dd2effed1494c89d79ecd
file + got/got.c
--- got/got.c
+++ got/got.c
@@ -4299,13 +4299,15 @@ usage_tree(void)
exit(1);
}
-static void
+static const struct got_error *
print_entry(struct got_tree_entry *te, const char *id, const char *path,
- const char *root_path)
+ const char *root_path, struct got_repository *repo)
{
+ const struct got_error *err = NULL;
int is_root_path = (strcmp(path, root_path) == 0);
const char *modestr = "";
mode_t mode = got_tree_entry_get_mode(te);
+ char *link_target = NULL;
path += strlen(root_path);
while (path[0] == '/')
@@ -4313,15 +4315,30 @@ print_entry(struct got_tree_entry *te, const char *id,
if (got_object_tree_entry_is_submodule(te))
modestr = "$";
- else if (S_ISLNK(mode))
+ else if (S_ISLNK(mode)) {
+ int i;
+
+ err = got_tree_entry_get_symlink_target(&link_target, te, repo);
+ if (err)
+ return err;
+ for (i = 0; i < strlen(link_target); i++) {
+ if (!isprint((unsigned char)link_target[i]))
+ link_target[i] = '?';
+ }
+
modestr = "@";
+ }
else if (S_ISDIR(mode))
modestr = "/";
else if (mode & S_IXUSR)
modestr = "*";
- printf("%s%s%s%s%s\n", id ? id : "", path,
- is_root_path ? "" : "/", got_tree_entry_get_name(te), modestr);
+ printf("%s%s%s%s%s%s%s\n", id ? id : "", path,
+ is_root_path ? "" : "/", got_tree_entry_get_name(te), modestr,
+ link_target ? " -> ": "", link_target ? link_target : "");
+
+ free(link_target);
+ return NULL;
}
static const struct got_error *
@@ -4363,8 +4380,10 @@ print_tree(const char *path, struct got_object_id *com
}
free(id_str);
}
- print_entry(te, id, path, root_path);
+ err = print_entry(te, id, path, root_path, repo);
free(id);
+ if (err)
+ goto done;
if (recurse && S_ISDIR(got_tree_entry_get_mode(te))) {
char *child_path;
blob - d17ff2d8455425992dbcd98fe8e0d53acfd2c208
file + include/got_error.h
--- include/got_error.h
+++ include/got_error.h
@@ -140,6 +140,7 @@
#define GOT_ERR_NO_REMOTE 123
#define GOT_ERR_FETCH_NO_BRANCH 124
#define GOT_ERR_FETCH_BAD_REF 125
+#define GOT_ERR_TREE_ENTRY_TYPE 126
static const struct got_error {
int code;
@@ -286,6 +287,7 @@ static const struct got_error {
{ GOT_ERR_NO_REMOTE, "remote repository not found" },
{ GOT_ERR_FETCH_NO_BRANCH, "could not find any branches to fetch" },
{ GOT_ERR_FETCH_BAD_REF, "reference cannot be fetched" },
+ { GOT_ERR_TREE_ENTRY_TYPE, "unexpected tree entry type" },
};
/*
blob - 461975117c98f1bb74df15d9317223d1940e4c6d
file + include/got_object.h
--- include/got_object.h
+++ include/got_object.h
@@ -191,6 +191,13 @@ const char *got_tree_entry_get_name(struct got_tree_en
/* Get the object ID of a tree entry. */
struct got_object_id *got_tree_entry_get_id(struct got_tree_entry *);
+/*
+ * Get a string containing the target path of a given a symlink tree entry.
+ * The caller should dispose of it with free(3).
+ */
+const struct got_error *got_tree_entry_get_symlink_target(char **,
+ struct got_tree_entry *, struct got_repository *);
+
/* Get the index of a tree entry. */
int got_tree_entry_get_index(struct got_tree_entry *);
blob - 60884259fffeeadac52f16b3ef8d210656e4c539
file + lib/object.c
--- lib/object.c
+++ lib/object.c
@@ -862,6 +862,42 @@ got_tree_entry_get_id(struct got_tree_entry *te)
return &te->id;
}
+const struct got_error *
+got_tree_entry_get_symlink_target(char **link_target, struct got_tree_entry *te,
+ struct got_repository *repo)
+{
+ const struct got_error *err = NULL;
+ struct got_blob_object *blob = NULL;
+ size_t len;
+
+ *link_target = NULL;
+
+ /* S_IFDIR check avoids confusing symlinks with submodules. */
+ if ((te->mode & (S_IFDIR | S_IFLNK)) != S_IFLNK)
+ return got_error(GOT_ERR_TREE_ENTRY_TYPE);
+
+ err = got_object_open_as_blob(&blob, repo,
+ got_tree_entry_get_id(te), PATH_MAX);
+ if (err)
+ return err;
+
+ err = got_object_blob_read_block(&len, blob);
+ if (err)
+ goto done;
+
+ *link_target = malloc(len + 1);
+ if (*link_target == NULL) {
+ err = got_error_from_errno("malloc");
+ goto done;
+ }
+ memcpy(*link_target, got_object_blob_get_read_buf(blob), len);
+ (*link_target)[len] = '\0';
+done:
+ if (blob)
+ got_object_blob_close(blob);
+ return err;
+}
+
int
got_tree_entry_get_index(struct got_tree_entry *te)
{
blob - 1b3bc07688dabd1f64ab5796add19f17d307dfc1
file + tog/tog.1
--- tog/tog.1
+++ tog/tog.1
@@ -304,6 +304,8 @@ Displayed tree entries may carry one of the following
.It $ Ta entry is a Git submodule
.El
.Pp
+Symbolic link entries are also annotated with the target path of the link.
+.Pp
The key bindings for
.Cm tog tree
are as follows:
blob - de21c04b04cf92a585fa3fd019dce29f5c235ff7
file + tog/tog.c
--- tog/tog.c
+++ tog/tog.c
@@ -18,6 +18,7 @@
#include <sys/stat.h>
#include <sys/ioctl.h>
+#include <ctype.h>
#include <errno.h>
#define _XOPEN_SOURCE_EXTENDED
#include <curses.h>
@@ -4622,7 +4623,7 @@ draw_tree_entries(struct tog_view *view,
struct got_tree_entry **selected_entry, int *ndisplayed,
const char *label, int show_ids, const char *parent_path,
struct got_tree_object *tree, int selected, int limit,
- int isroot, struct tog_colors *colors)
+ int isroot, struct tog_colors *colors, struct got_repository *repo)
{
const struct got_error *err = NULL;
struct got_tree_entry *te;
@@ -4693,7 +4694,7 @@ draw_tree_entries(struct tog_view *view,
nentries = got_object_tree_get_nentries(tree);
for (i = got_tree_entry_get_index(te); i < nentries; i++) {
- char *line = NULL, *id_str = NULL;
+ char *line = NULL, *id_str = NULL, *link_target = NULL;
const char *modestr = "";
mode_t mode;
@@ -4709,18 +4710,35 @@ draw_tree_entries(struct tog_view *view,
}
if (got_object_tree_entry_is_submodule(te))
modestr = "$";
- else if (S_ISLNK(mode))
+ else if (S_ISLNK(mode)) {
+ int i;
+
+ err = got_tree_entry_get_symlink_target(&link_target,
+ te, repo);
+ if (err) {
+ free(id_str);
+ return err;
+ }
+ for (i = 0; i < strlen(link_target); i++) {
+ if (!isprint((unsigned char)link_target[i]))
+ link_target[i] = '?';
+ }
modestr = "@";
+ }
else if (S_ISDIR(mode))
modestr = "/";
else if (mode & S_IXUSR)
modestr = "*";
- if (asprintf(&line, "%s %s%s", id_str ? id_str : "",
- got_tree_entry_get_name(te), modestr) == -1) {
+ if (asprintf(&line, "%s %s%s%s%s", id_str ? id_str : "",
+ got_tree_entry_get_name(te), modestr,
+ link_target ? " -> ": "",
+ link_target ? link_target : "") == -1) {
free(id_str);
+ free(link_target);
return got_error_from_errno("asprintf");
}
free(id_str);
+ free(link_target);
err = format_line(&wline, &width, line, view->ncols, 0);
if (err) {
free(line);
@@ -5121,7 +5139,7 @@ show_tree_view(struct tog_view *view)
&s->last_displayed_entry, &s->selected_entry,
&s->ndisplayed, s->tree_label, s->show_ids, parent_path,
s->tree, s->selected, view->nlines, s->tree == s->root,
- &s->colors);
+ &s->colors, s->repo);
free(parent_path);
view_vborder(view);
[prev in list] [next in list] [prev in thread] [next in thread]
Configure |
About |
News |
Add a list |
Sponsored by KoreLogic