Skip to content

Commit

Permalink
Merge pull request #504 from rgburke/status-tracking-info
Browse files Browse the repository at this point in the history
Show tracking info in tig status
  • Loading branch information
jonas committed Jun 8, 2016
2 parents ebb92c1 + 53b2bba commit 68b7868
Show file tree
Hide file tree
Showing 2 changed files with 180 additions and 1 deletion.
76 changes: 75 additions & 1 deletion src/status.c
Original file line number Diff line number Diff line change
Expand Up @@ -199,6 +199,71 @@ status_restore(struct view *view)
clear_position(&view->prev_pos);
}

static bool
status_branch_tracking_info(char *buf, size_t buf_len, const char *head,
const char *remote)
{
if (!string_nformat(buf, buf_len, NULL, "%s...%s",
head, remote)) {
return false;
}

const char *tracking_info_argv[] = {
"git", "rev-list", "--left-right", buf, NULL
};

struct io io;

if (!io_run(&io, IO_RD, repo.cdup, NULL, tracking_info_argv)) {
return false;
}

struct buffer result = { 0 };
int ahead = 0;
int behind = 0;

while (io_get(&io, &result, '\n', true)) {
if (result.size > 0 && result.data) {
if (result.data[0] == '<') {
ahead++;
} else if (result.data[0] == '>') {
behind++;
}
}
}

bool io_failed = io_error(&io);
io_done(&io);

if (io_failed) {
return false;
}

if (ahead == 0 && behind == 0) {
return string_nformat(buf, buf_len, NULL,
"Your branch is up-to-date with '%s'.",
remote);
} else if (ahead > 0 && behind > 0) {
return string_nformat(buf, buf_len, NULL,
"Your branch and '%s' have diverged, "
"and have %d and %d different commits "
"each, respectively",
remote, ahead, behind);
} else if (ahead > 0) {
return string_nformat(buf, buf_len, NULL,
"Your branch is ahead of '%s' by "
"%d commit%s.", remote, ahead,
ahead > 1 ? "s" : "");
} else if (behind > 0) {
return string_nformat(buf, buf_len, NULL,
"Your branch is behind '%s' by "
"%d commit%s.", remote, behind,
behind > 1 ? "s" : "");
}

return false;
}

static void
status_update_onbranch(void)
{
Expand All @@ -224,6 +289,7 @@ status_update_onbranch(void)
for (i = 0; i < ARRAY_SIZE(paths); i++) {
const char *prefix = paths[i][2];
const char *head = repo.head;
const char *tracking_info = "";

if (!string_format(buf, "%s/%s", repo.git_dir, paths[i][0]) ||
lstat(buf, &stat) < 0)
Expand All @@ -248,9 +314,17 @@ status_update_onbranch(void)

if (ref && strcmp(ref->name, "HEAD"))
head = ref->name;
} else if (!paths[i][1] && *repo.remote) {
if (status_branch_tracking_info(buf, sizeof(buf),
head, repo.remote)) {
tracking_info = buf;
}
}

if (!string_format(status_onbranch, "%s %s", prefix, head))
const char *fmt = *tracking_info == '\0' ? "%s %s" : "%s %s. %s";

if (!string_format(status_onbranch, fmt,
prefix, head, tracking_info))
string_copy(status_onbranch, repo.head);
return;
}
Expand Down
105 changes: 105 additions & 0 deletions test/status/on-branch-tracking-info-test
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
#!/bin/sh

. libtest.sh
. libgit.sh

export LINES=10

test_setup_work_dir()
{
create_repo_from_tgz "$base_dir/files/refs-repo.tgz"

git checkout -b ahead
echo test > test.txt
git add test.txt
git_commit -m "Ahead branch"
git checkout master

git checkout -b diverged HEAD~2
echo test > test.txt
git add test.txt
git_commit -m "Diverged branch"
git checkout master
}

test_case up-to-date-with-remote-master \
--args='status' <<EOF
On branch master. Your branch is up-to-date with 'origin/master'.
Changes to be committed:
(no files)
Changes not staged for commit:
(no files)
Untracked files:
(no files)
[status] Nothing to update 100%
EOF

test_case behind-remote-master \
--args='status' \
--before="git reset --hard HEAD~2" \
--after="git reset --hard origin/master" <<EOF
On branch master. Your branch is behind 'origin/master' by 2 commits.
Changes to be committed:
(no files)
Changes not staged for commit:
(no files)
Untracked files:
(no files)
[status] Nothing to update 100%
EOF

test_case ahead-of-remote-master \
--args='status' \
--before="git merge ahead" \
--after="git reset --hard origin/master" <<EOF
On branch master. Your branch is ahead of 'origin/master' by 1 commit.
Changes to be committed:
(no files)
Changes not staged for commit:
(no files)
Untracked files:
(no files)
[status] Nothing to update 100%
EOF

test_case diverged-from-remote-master \
--args='status' \
--before="git reset --hard diverged" \
--after="git reset --hard origin/master" <<EOF
On branch master. Your branch and 'origin/master' have diverged, and have 1 and
Changes to be committed:
(no files)
Changes not staged for commit:
(no files)
Untracked files:
(no files)
[status] Nothing to update 100%
EOF

run_test_cases

add_exec_prefix()
{
code="$(cat "$1")"
if [ -n "$code" ]; then
echo "$code" | sed -e 's/^[ ]*//' -e '/^$/d' -e 's/^/:exec @/'
fi
}

tig_script "all" "
$(for name in $(cat test-cases); do
add_exec_prefix "$name-before"
echo :save-display all-$name.screen
add_exec_prefix "$name-after"
done)
"

test_tig status

for name in $(cat test-cases); do
assert_equals "all-$name.screen" < "$name.expected"
done

0 comments on commit 68b7868

Please sign in to comment.