[gnome-builder] git: special case git-worktree links



commit ebe824ed7da357f7f7fe8cd2d4e78004657e104d
Author: Christian Hergert <chergert redhat com>
Date:   Fri Mar 30 13:09:00 2018 -0700

    git: special case git-worktree links
    
    This ensures we get a proper branch name other than "HEAD" when we find
    a git-worktree link. The normal discover process finds the directory
    just fine, but since we're already doing the work here to track it down,
    we can just set the resulting GFile too.

 src/plugins/git/ide-git-vcs.c | 55 +++++++++++++++++++++++++++++++++++++++----
 1 file changed, 51 insertions(+), 4 deletions(-)
---
diff --git a/src/plugins/git/ide-git-vcs.c b/src/plugins/git/ide-git-vcs.c
index 3ceee165e..1853f4e11 100644
--- a/src/plugins/git/ide-git-vcs.c
+++ b/src/plugins/git/ide-git-vcs.c
@@ -51,6 +51,12 @@ struct _IdeGitVcs
   GFile          *working_directory;
   GFileMonitor   *monitor;
 
+  /*
+   * If we're in a worktree, we might have a permanent branch name
+   * as we can't change branches.
+   */
+  gchar          *worktree_branch;
+
   guint           changed_timeout;
 
   guint           reloading : 1;
@@ -166,7 +172,6 @@ ide_git_vcs_discover (IdeGitVcs  *self,
   g_autoptr(GFile) parent = NULL;
   g_autoptr(GFile) git = NULL;
   g_autoptr(GFile) child = NULL;
-  GFile *ret;
 
   g_assert (IDE_IS_GIT_VCS (self));
   g_assert (G_IS_FILE (file));
@@ -223,9 +228,7 @@ ide_git_vcs_discover (IdeGitVcs  *self,
       return NULL;
     }
 
-  ret = ide_git_vcs_discover (self, parent, error);
-
-  return ret;
+  return ide_git_vcs_discover (self, parent, error);
 }
 
 static GgitRepository *
@@ -256,6 +259,45 @@ ide_git_vcs_load (IdeGitVcs  *self,
         return NULL;
     }
 
+  /* If @location is a regular file, we might have a git-worktree link */
+  if (g_file_query_file_type (location, 0, NULL) == G_FILE_TYPE_REGULAR)
+    {
+      g_autofree gchar *contents = NULL;
+      gsize len;
+
+      if (g_file_load_contents (location, NULL, &contents, &len, NULL, NULL))
+        {
+          IdeLineReader reader;
+          gchar *line;
+          gsize line_len;
+
+          ide_line_reader_init (&reader, contents, len);
+
+          while ((line = ide_line_reader_next (&reader, &line_len)))
+            {
+              line[line_len] = 0;
+
+              if (g_str_has_prefix (line, "gitdir: "))
+                {
+                  const gchar *branch;
+
+                  g_clear_object (&location);
+                  location = g_file_new_for_path (line + strlen ("gitdir: "));
+
+                  /*
+                   * Worktrees only have a single branch, and it is the name
+                   * of the suffix of .git/worktrees/<name>
+                   */
+                  if (self->worktree_branch == NULL &&
+                      (branch = strrchr (line, G_DIR_SEPARATOR)))
+                    self->worktree_branch = g_strdup (branch + 1);
+
+                  break;
+                }
+            }
+        }
+    }
+
   uri = g_file_get_uri (location);
   g_debug ("Discovered .git location at ā€œ%sā€", uri);
 
@@ -515,9 +557,13 @@ ide_git_vcs_get_branch_name (IdeVcs *vcs)
   g_assert (IDE_IS_GIT_VCS (self));
 
   g_mutex_lock (&self->repository_mutex);
+  ret = g_strdup (self->worktree_branch);
   ref = ggit_repository_get_head (self->repository, NULL);
   g_mutex_unlock (&self->repository_mutex);
 
+  if (ret != NULL)
+    return ret;
+
   if (ref != NULL)
     {
       ret = g_strdup (ggit_ref_get_shorthand (ref));
@@ -751,6 +797,7 @@ ide_git_vcs_finalize (GObject *object)
   IDE_ENTRY;
 
   g_mutex_clear (&self->repository_mutex);
+  g_clear_pointer (&self->worktree_branch, g_free);
 
   G_OBJECT_CLASS (ide_git_vcs_parent_class)->finalize (object);
 


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]