Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Show tracking info in tig status #504

Merged
merged 1 commit into from
Jun 8, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
};
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry I'm a little late to the party, but I happened to notice this while pulling master. You can actually do git rev-list --left-right --count to get just the two counts. Probably not a big deal, but it would save a little pipe and parsing overhead.


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