Skip to content

Commit 4f9f8e0

Browse files
author
Edward Thomson
authored
Merge pull request libgit2#3436 from pks-t/libgit2-worktree
Worktree implementation
2 parents 43275f5 + 1ba242c commit 4f9f8e0

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

75 files changed

+2423
-123
lines changed

include/git2/branch.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -245,6 +245,18 @@ GIT_EXTERN(int) git_branch_upstream_name(
245245
GIT_EXTERN(int) git_branch_is_head(
246246
const git_reference *branch);
247247

248+
/**
249+
* Determine if the current branch is checked out in any linked
250+
* repository.
251+
*
252+
* @param branch Reference to the branch.
253+
*
254+
* @return 1 if branch is checked out, 0 if it isn't,
255+
* error code otherwise.
256+
*/
257+
GIT_EXTERN(int) git_branch_is_checked_out(
258+
const git_reference *branch);
259+
248260
/**
249261
* Return the name of remote that the remote tracking branch belongs to.
250262
*

include/git2/errors.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,7 @@ typedef enum {
100100
GITERR_REBASE,
101101
GITERR_FILESYSTEM,
102102
GITERR_PATCH,
103+
GITERR_WORKTREE
103104
} git_error_t;
104105

105106
/**

include/git2/repository.h

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,17 @@ GIT_BEGIN_DECL
3535
* @return 0 or an error code
3636
*/
3737
GIT_EXTERN(int) git_repository_open(git_repository **out, const char *path);
38+
/**
39+
* Open working tree as a repository
40+
*
41+
* Open the working directory of the working tree as a normal
42+
* repository that can then be worked on.
43+
*
44+
* @param out Output pointer containing opened repository
45+
* @param wt Working tree to open
46+
* @return 0 or an error code
47+
*/
48+
GIT_EXTERN(int) git_repository_open_from_worktree(git_repository **out, git_worktree *wt);
3849

3950
/**
4051
* Create a "fake" repository to wrap an object database
@@ -334,6 +345,17 @@ GIT_EXTERN(int) git_repository_init_ext(
334345
*/
335346
GIT_EXTERN(int) git_repository_head(git_reference **out, git_repository *repo);
336347

348+
/**
349+
* Retrieve the referenced HEAD for the worktree
350+
*
351+
* @param out pointer to the reference which will be retrieved
352+
* @param repo a repository object
353+
* @param name name of the worktree to retrieve HEAD for
354+
* @return 0 when successful, error-code otherwise
355+
*/
356+
GIT_EXTERN(int) git_repository_head_for_worktree(git_reference **out, git_repository *repo,
357+
const char *name);
358+
337359
/**
338360
* Check if a repository's HEAD is detached
339361
*
@@ -346,6 +368,20 @@ GIT_EXTERN(int) git_repository_head(git_reference **out, git_repository *repo);
346368
*/
347369
GIT_EXTERN(int) git_repository_head_detached(git_repository *repo);
348370

371+
/*
372+
* Check if a worktree's HEAD is detached
373+
*
374+
* A worktree's HEAD is detached when it points directly to a
375+
* commit instead of a branch.
376+
*
377+
* @param repo a repository object
378+
* @param name name of the worktree to retrieve HEAD for
379+
* @return 1 if HEAD is detached, 0 if its not; error code if
380+
* there was an error
381+
*/
382+
GIT_EXTERN(int) git_repository_head_detached_for_worktree(git_repository *repo,
383+
const char *name);
384+
349385
/**
350386
* Check if the current branch is unborn
351387
*
@@ -370,6 +406,42 @@ GIT_EXTERN(int) git_repository_head_unborn(git_repository *repo);
370406
*/
371407
GIT_EXTERN(int) git_repository_is_empty(git_repository *repo);
372408

409+
/**
410+
* List of items which belong to the git repository layout
411+
*/
412+
typedef enum {
413+
GIT_REPOSITORY_ITEM_GITDIR,
414+
GIT_REPOSITORY_ITEM_WORKDIR,
415+
GIT_REPOSITORY_ITEM_COMMONDIR,
416+
GIT_REPOSITORY_ITEM_INDEX,
417+
GIT_REPOSITORY_ITEM_OBJECTS,
418+
GIT_REPOSITORY_ITEM_REFS,
419+
GIT_REPOSITORY_ITEM_PACKED_REFS,
420+
GIT_REPOSITORY_ITEM_REMOTES,
421+
GIT_REPOSITORY_ITEM_CONFIG,
422+
GIT_REPOSITORY_ITEM_INFO,
423+
GIT_REPOSITORY_ITEM_HOOKS,
424+
GIT_REPOSITORY_ITEM_LOGS,
425+
GIT_REPOSITORY_ITEM_MODULES,
426+
GIT_REPOSITORY_ITEM_WORKTREES
427+
} git_repository_item_t;
428+
429+
/**
430+
* Get the location of a specific repository file or directory
431+
*
432+
* This function will retrieve the path of a specific repository
433+
* item. It will thereby honor things like the repository's
434+
* common directory, gitdir, etc. In case a file path cannot
435+
* exist for a given item (e.g. the working directory of a bare
436+
* repository), an error is returned.
437+
*
438+
* @param out Buffer to store the path at
439+
* @param repo Repository to get path for
440+
* @param item The repository item for which to retrieve the path
441+
* @return 0 on success, otherwise a negative value
442+
*/
443+
GIT_EXTERN(int) git_repository_item_path(git_buf *out, git_repository *repo, git_repository_item_t item);
444+
373445
/**
374446
* Get the path of this repository
375447
*
@@ -392,6 +464,17 @@ GIT_EXTERN(const char *) git_repository_path(git_repository *repo);
392464
*/
393465
GIT_EXTERN(const char *) git_repository_workdir(git_repository *repo);
394466

467+
/**
468+
* Get the path of the shared common directory for this repository
469+
*
470+
* If the repository is bare is not a worktree, the git directory
471+
* path is returned.
472+
*
473+
* @param repo A repository object
474+
* @return the path to the common dir
475+
*/
476+
GIT_EXTERN(const char *) git_repository_commondir(git_repository *repo);
477+
395478
/**
396479
* Set the path to the working directory for this repository
397480
*
@@ -420,6 +503,14 @@ GIT_EXTERN(int) git_repository_set_workdir(
420503
*/
421504
GIT_EXTERN(int) git_repository_is_bare(git_repository *repo);
422505

506+
/**
507+
* Check if a repository is a linked work tree
508+
*
509+
* @param repo Repo to test
510+
* @return 1 if the repository is a linked work tree, 0 otherwise.
511+
*/
512+
GIT_EXTERN(int) git_repository_is_worktree(git_repository *repo);
513+
423514
/**
424515
* Get the configuration file for this repository.
425516
*

include/git2/types.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,9 @@ typedef struct git_refdb_backend git_refdb_backend;
104104
*/
105105
typedef struct git_repository git_repository;
106106

107+
/** Representation of a working tree */
108+
typedef struct git_worktree git_worktree;
109+
107110
/** Representation of a generic object in a repository */
108111
typedef struct git_object git_object;
109112

include/git2/worktree.h

Lines changed: 161 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,161 @@
1+
/*
2+
* Copyright (C) the libgit2 contributors. All rights reserved.
3+
*
4+
* This file is part of libgit2, distributed under the GNU GPL v2 with
5+
* a Linking Exception. For full terms see the included COPYING file.
6+
*/
7+
#ifndef INCLUDE_git_worktree_h__
8+
#define INCLUDE_git_worktree_h__
9+
10+
#include "common.h"
11+
#include "buffer.h"
12+
#include "types.h"
13+
#include "strarray.h"
14+
15+
/**
16+
* @file git2/worktrees.h
17+
* @brief Git worktree related functions
18+
* @defgroup git_commit Git worktree related functions
19+
* @ingroup Git
20+
* @{
21+
*/
22+
GIT_BEGIN_DECL
23+
24+
/**
25+
* List names of linked working trees
26+
*
27+
* The returned list should be released with `git_strarray_free`
28+
* when no longer needed.
29+
*
30+
* @param out pointer to the array of working tree names
31+
* @param repo the repo to use when listing working trees
32+
* @return 0 or an error code
33+
*/
34+
GIT_EXTERN(int) git_worktree_list(git_strarray *out, git_repository *repo);
35+
36+
/**
37+
* Lookup a working tree by its name for a given repository
38+
*
39+
* @param out Output pointer to looked up worktree or `NULL`
40+
* @param repo The repository containing worktrees
41+
* @param name Name of the working tree to look up
42+
* @return 0 or an error code
43+
*/
44+
GIT_EXTERN(int) git_worktree_lookup(git_worktree **out, git_repository *repo, const char *name);
45+
46+
/**
47+
* Free a previously allocated worktree
48+
*
49+
* @param wt worktree handle to close. If NULL nothing occurs.
50+
*/
51+
GIT_EXTERN(void) git_worktree_free(git_worktree *wt);
52+
53+
/**
54+
* Check if worktree is valid
55+
*
56+
* A valid worktree requires both the git data structures inside
57+
* the linked parent repository and the linked working copy to be
58+
* present.
59+
*
60+
* @param wt Worktree to check
61+
* @return 0 when worktree is valid, error-code otherwise
62+
*/
63+
GIT_EXTERN(int) git_worktree_validate(const git_worktree *wt);
64+
65+
/**
66+
* Add a new working tree
67+
*
68+
* Add a new working tree for the repository, that is create the
69+
* required data structures inside the repository and check out
70+
* the current HEAD at `path`
71+
*
72+
* @param out Output pointer containing new working tree
73+
* @param repo Repository to create working tree for
74+
* @param name Name of the working tree
75+
* @param path Path to create working tree at
76+
* @return 0 or an error code
77+
*/
78+
GIT_EXTERN(int) git_worktree_add(git_worktree **out, git_repository *repo, const char *name, const char *path);
79+
80+
/**
81+
* Lock worktree if not already locked
82+
*
83+
* Lock a worktree, optionally specifying a reason why the linked
84+
* working tree is being locked.
85+
*
86+
* @param wt Worktree to lock
87+
* @param reason Reason why the working tree is being locked
88+
* @return 0 on success, non-zero otherwise
89+
*/
90+
GIT_EXTERN(int) git_worktree_lock(git_worktree *wt, char *reason);
91+
92+
/**
93+
* Unlock a locked worktree
94+
*
95+
* @param wt Worktree to unlock
96+
* @return 0 on success, 1 if worktree was not locked, error-code
97+
* otherwise
98+
*/
99+
GIT_EXTERN(int) git_worktree_unlock(git_worktree *wt);
100+
101+
/**
102+
* Check if worktree is locked
103+
*
104+
* A worktree may be locked if the linked working tree is stored
105+
* on a portable device which is not available.
106+
*
107+
* @param reason Buffer to store reason in. If NULL no reason is stored.
108+
* @param wt Worktree to check
109+
* @return 0 when the working tree not locked, a value greater
110+
* than zero if it is locked, less than zero if there was an
111+
* error
112+
*/
113+
GIT_EXTERN(int) git_worktree_is_locked(git_buf *reason, const git_worktree *wt);
114+
115+
/**
116+
* Flags which can be passed to git_worktree_prune to alter its
117+
* behavior.
118+
*/
119+
typedef enum {
120+
/* Prune working tree even if working tree is valid */
121+
GIT_WORKTREE_PRUNE_VALID = 1u << 0,
122+
/* Prune working tree even if it is locked */
123+
GIT_WORKTREE_PRUNE_LOCKED = 1u << 1,
124+
/* Prune checked out working tree */
125+
GIT_WORKTREE_PRUNE_WORKING_TREE = 1u << 2,
126+
} git_worktree_prune_t;
127+
128+
/**
129+
* Is the worktree prunable with the given set of flags?
130+
*
131+
* A worktree is not prunable in the following scenarios:
132+
*
133+
* - the worktree is linking to a valid on-disk worktree. The
134+
* GIT_WORKTREE_PRUNE_VALID flag will cause this check to be
135+
* ignored.
136+
* - the worktree is not valid but locked. The
137+
* GIT_WORKRTEE_PRUNE_LOCKED flag will cause this check to be
138+
* ignored.
139+
*
140+
* If the worktree is not valid and not locked or if the above
141+
* flags have been passed in, this function will return a
142+
* positive value.
143+
*/
144+
GIT_EXTERN(int) git_worktree_is_prunable(git_worktree *wt, unsigned flags);
145+
146+
/**
147+
* Prune working tree
148+
*
149+
* Prune the working tree, that is remove the git data
150+
* structures on disk. The repository will only be pruned of
151+
* `git_worktree_is_prunable` succeeds.
152+
*
153+
* @param wt Worktree to prune
154+
* @param flags git_worktree_prune_t flags
155+
* @return 0 or an error code
156+
*/
157+
GIT_EXTERN(int) git_worktree_prune(git_worktree *wt, unsigned flags);
158+
159+
/** @} */
160+
GIT_END_DECL
161+
#endif

0 commit comments

Comments
 (0)