Skip to content

Commit

Permalink
git-changebar: Fix in-repository paths on Windows
Browse files Browse the repository at this point in the history
Git uses its own path representation for files inside its tree, which
follows the UNIX path style (forward slashes).  So properly convert
internal paths from native to Git paths.

See libgit2/libgit2#3012

Part of Issue geany#214.
  • Loading branch information
b4n committed May 26, 2015
1 parent cbb4f1b commit 6a396b1
Showing 1 changed file with 59 additions and 5 deletions.
64 changes: 59 additions & 5 deletions git-changebar/src/gcb-plugin.c
Original file line number Diff line number Diff line change
Expand Up @@ -290,6 +290,58 @@ monitor_head_ref (git_repository *repo,
return monitor;
}

/* checks whether @path points somewhere inside @dir and returns the pointer
* inside @path starting the relative path, or NULL */
static const gchar *
path_dir_contains (const gchar *dir,
const gchar *path)
{
#ifdef G_OS_WIN32
/* FIXME: handle drive letters and such */
# define NORM_PATH_CH(c) (((c) == '\\') ? '/' : (c))
#else
# define NORM_PATH_CH(c) (c)
#endif

g_return_val_if_fail (dir != NULL, NULL);
g_return_val_if_fail (path != NULL, NULL);

while (*dir && NORM_PATH_CH (*dir) == NORM_PATH_CH (*path)) {
dir++, path++;
}

return *dir ? NULL : path;
}

/* gets the Git path for @repo pointing to @sys_path, or NULL */
static gchar *
get_path_in_repository (git_repository *repo,
const gchar *sys_path)
{
const gchar *workdir = git_repository_workdir (repo);
const gchar *rel_path = path_dir_contains (workdir, sys_path);

#ifdef G_OS_WIN32
if (rel_path) {
/* we want an internal Git path, which uses UNIX format */
gchar *p;
gchar *repo_path = g_strdup (rel_path);

for (p = repo_path; *p; p++) {
if (*p == '\\') {
*p = '/';
}
}

return repo_path;
}

return NULL;
#else
return g_strdup (rel_path);
#endif
}

static gpointer
worker_thread (gpointer data)
{
Expand All @@ -303,7 +355,7 @@ worker_thread (gpointer data)
const gchar *path = job->path;

if (repo && (job->force ||
! g_str_has_prefix (path, git_repository_workdir (repo)))) {
! path_dir_contains (path, git_repository_workdir (repo)))) {
/* FIXME: this can fail with nested repositories */
git_repository_free (repo);
repo = NULL;
Expand All @@ -330,12 +382,14 @@ worker_thread (gpointer data)
}
}

job->blob = NULL;
if (repo) {
const gchar *relpath = path + strlen (git_repository_workdir (repo));
gchar *relpath = get_path_in_repository (repo, path);

job->blob = repo_get_file_blob (repo, relpath);
} else {
job->blob = NULL;
if (relpath) {
job->blob = repo_get_file_blob (repo, relpath);
g_free (relpath);
}
}

g_idle_add_full (G_PRIORITY_LOW, report_work_in_idle, job, free_job);
Expand Down

0 comments on commit 6a396b1

Please sign in to comment.