Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
G
git2
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
lvzhengyang
git2
Commits
1ee2ef87
Commit
1ee2ef87
authored
May 21, 2013
by
Edward Thomson
Committed by
Russell Belfer
Jun 17, 2013
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
status access by index, providing more details to callers
parent
09c2f91c
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
255 additions
and
66 deletions
+255
-66
include/git2/status.h
+63
-0
include/git2/types.h
+3
-0
src/status.c
+166
-66
src/status.h
+23
-0
No files found.
include/git2/status.h
View file @
1ee2ef87
...
...
@@ -174,10 +174,73 @@ typedef struct {
git_strarray
pathspec
;
}
git_status_options
;
/**
* A status entry, providing the differences between the file as it exists
* in HEAD and the index, and providing the differences between the index
* and the working directory.
*
* The `status` value provides the status flags for this file.
*
* The `head_to_index` value provides detailed information about the
* differences between the file in HEAD and the file in the index.
*
* The `index_to_workdir` value provides detailed information about the
* differences between the file in the index and the file in the
* working directory.
*/
typedef
struct
{
git_status_t
status
;
git_diff_delta
*
head_to_index
;
git_diff_delta
*
index_to_workdir
;
}
git_status_entry
;
#define GIT_STATUS_OPTIONS_VERSION 1
#define GIT_STATUS_OPTIONS_INIT {GIT_STATUS_OPTIONS_VERSION}
/**
* Gather file status information and populate the `git_status_list`.
*
* @param out Pointer to store the status results in
* @param repo Repository object
* @param opts Status options structure
* @return 0 on success or error code
*/
GIT_EXTERN
(
int
)
git_status_list_new
(
git_status_list
**
out
,
git_repository
*
repo
,
const
git_status_options
*
opts
);
/**
* Gets the count of status entries in this list.
*
* @param statuslist Existing status list object
* @return the number of status entries
*/
GIT_EXTERN
(
size_t
)
git_status_list_entrycount
(
git_status_list
*
statuslist
);
/**
* Get a pointer to one of the entries in the status list.
*
* The entry is not modifiable and should not be freed.
*
* @param statuslist Existing status list object
* @param idx Position of the entry
* @return Pointer to the entry; NULL if out of bounds
*/
GIT_EXTERN
(
const
git_status_entry
*
)
git_status_byindex
(
git_status_list
*
statuslist
,
size_t
idx
);
/**
* Free an existing status list
*
* @param statuslist Existing status list object
*/
GIT_EXTERN
(
void
)
git_status_list_free
(
git_status_list
*
statuslist
);
/**
* Gather file status information and run callbacks as requested.
*
* This is an extended version of the `git_status_foreach()` API that
...
...
include/git2/types.h
View file @
1ee2ef87
...
...
@@ -174,6 +174,9 @@ typedef struct git_reference_iterator git_reference_iterator;
/** Merge heads, the input to merge */
typedef
struct
git_merge_head
git_merge_head
;
/** Representation of a status collection */
typedef
struct
git_status_list
git_status_list
;
/** Basic type of any Git reference. */
typedef
enum
{
...
...
src/status.c
View file @
1ee2ef87
...
...
@@ -11,6 +11,7 @@
#include "hash.h"
#include "vector.h"
#include "tree.h"
#include "status.h"
#include "git2/status.h"
#include "repository.h"
#include "ignore.h"
...
...
@@ -77,71 +78,105 @@ static unsigned int workdir_delta2status(git_delta_t workdir_status)
return
st
;
}
typedef
struct
{
git_status_cb
cb
;
void
*
payload
;
const
git_status_options
*
opts
;
}
status_user_callback
;
static
bool
status_is_included
(
git_status_list
*
statuslist
,
git_diff_delta
*
head2idx
,
git_diff_delta
*
idx2wd
)
{
/* if excluding submodules and this is a submodule everywhere */
if
((
statuslist
->
opts
.
flags
&
GIT_STATUS_OPT_EXCLUDE_SUBMODULES
)
!=
0
)
{
bool
in_tree
=
(
head2idx
&&
head2idx
->
status
!=
GIT_DELTA_ADDED
);
bool
in_index
=
(
head2idx
&&
head2idx
->
status
!=
GIT_DELTA_DELETED
);
bool
in_wd
=
(
idx2wd
&&
idx2wd
->
status
!=
GIT_DELTA_DELETED
);
if
((
!
in_tree
||
head2idx
->
old_file
.
mode
==
GIT_FILEMODE_COMMIT
)
&&
(
!
in_index
||
head2idx
->
new_file
.
mode
==
GIT_FILEMODE_COMMIT
)
&&
(
!
in_wd
||
idx2wd
->
new_file
.
mode
==
GIT_FILEMODE_COMMIT
))
return
0
;
}
static
int
status_invoke_cb
(
git_diff_delta
*
h2i
,
git_diff_delta
*
i2w
,
void
*
payload
)
return
1
;
}
static
git_status_t
status_compute
(
git_diff_delta
*
head2idx
,
git_diff_delta
*
idx2wd
)
{
status_user_callback
*
usercb
=
payload
;
const
char
*
path
=
NULL
;
unsigned
int
status
=
0
;
git_status_t
status
=
0
;
if
(
i2w
)
{
path
=
i2w
->
old_file
.
path
;
status
|=
workdir_delta2status
(
i2w
->
status
);
}
if
(
h2i
)
{
path
=
h2i
->
old_file
.
path
;
status
|=
index_delta2status
(
h2i
->
status
);
}
if
(
head2idx
)
status
|=
index_delta2status
(
head2idx
->
status
);
/* if excluding submodules and this is a submodule everywhere */
if
(
usercb
->
opts
&&
(
usercb
->
opts
->
flags
&
GIT_STATUS_OPT_EXCLUDE_SUBMODULES
)
!=
0
)
{
bool
in_tree
=
(
h2i
&&
h2i
->
status
!=
GIT_DELTA_ADDED
);
bool
in_index
=
(
h2i
&&
h2i
->
status
!=
GIT_DELTA_DELETED
);
bool
in_wd
=
(
i2w
&&
i2w
->
status
!=
GIT_DELTA_DELETED
);
if
(
idx2wd
)
status
|=
workdir_delta2status
(
idx2wd
->
status
);
if
((
!
in_tree
||
h2i
->
old_file
.
mode
==
GIT_FILEMODE_COMMIT
)
&&
(
!
in_index
||
h2i
->
new_file
.
mode
==
GIT_FILEMODE_COMMIT
)
&&
(
!
in_wd
||
i2w
->
new_file
.
mode
==
GIT_FILEMODE_COMMIT
))
return
0
;
}
return
status
;
}
static
int
status_collect
(
git_diff_delta
*
head2idx
,
git_diff_delta
*
idx2wd
,
void
*
payload
)
{
git_status_list
*
statuslist
=
payload
;
git_status_entry
*
status_entry
;
if
(
!
status_is_included
(
statuslist
,
head2idx
,
idx2wd
))
return
0
;
status_entry
=
git__malloc
(
sizeof
(
git_status_entry
));
GITERR_CHECK_ALLOC
(
status_entry
);
status_entry
->
status
=
status_compute
(
head2idx
,
idx2wd
);
status_entry
->
head_to_index
=
head2idx
;
status_entry
->
index_to_workdir
=
idx2wd
;
git_vector_insert
(
&
statuslist
->
paired
,
status_entry
);
return
usercb
->
cb
(
path
,
status
,
usercb
->
payload
)
;
return
0
;
}
int
git_status_foreach_ext
(
git_status_list
*
git_status_list_alloc
(
void
)
{
git_status_list
*
statuslist
=
NULL
;
if
((
statuslist
=
git__calloc
(
1
,
sizeof
(
git_status_list
)))
==
NULL
||
git_vector_init
(
&
statuslist
->
paired
,
0
,
NULL
)
<
0
)
return
NULL
;
return
statuslist
;
}
int
git_status_list_new
(
git_status_list
**
out
,
git_repository
*
repo
,
const
git_status_options
*
opts
,
git_status_cb
cb
,
void
*
payload
)
const
git_status_options
*
opts
)
{
int
err
=
0
;
git_status_list
*
statuslist
=
NULL
;
git_diff_options
diffopt
=
GIT_DIFF_OPTIONS_INIT
;
git_diff_list
*
head2idx
=
NULL
,
*
idx2wd
=
NULL
;
git_tree
*
head
=
NULL
;
git_status_show_t
show
=
opts
?
opts
->
show
:
GIT_STATUS_SHOW_INDEX_AND_WORKDIR
;
status_user_callback
usercb
;
int
error
=
0
;
assert
(
show
<=
GIT_STATUS_SHOW_INDEX_THEN_WORKDIR
);
*
out
=
NULL
;
GITERR_CHECK_VERSION
(
opts
,
GIT_STATUS_OPTIONS_VERSION
,
"git_status_options"
);
if
(
show
!=
GIT_STATUS_SHOW_INDEX_ONLY
&&
(
err
=
git_repository__ensure_not_bare
(
repo
,
"status"
))
<
0
)
return
err
;
if
((
error
=
git_repository__ensure_not_bare
(
repo
,
"status"
))
<
0
)
return
error
;
/* if there is no HEAD, that's okay - we'll make an empty iterator */
if
(((
err
=
git_repository_head_tree
(
&
head
,
repo
))
<
0
)
&&
!
(
err
==
GIT_ENOTFOUND
||
err
==
GIT_EORPHANEDHEAD
))
return
err
;
if
(((
error
=
git_repository_head_tree
(
&
head
,
repo
))
<
0
)
&&
!
(
error
==
GIT_ENOTFOUND
||
error
==
GIT_EORPHANEDHEAD
))
return
error
;
statuslist
=
git_status_list_alloc
();
GITERR_CHECK_ALLOC
(
statuslist
);
memcpy
(
&
statuslist
->
opts
,
opts
,
sizeof
(
git_status_options
));
memcpy
(
&
diffopt
.
pathspec
,
&
opts
->
pathspec
,
sizeof
(
diffopt
.
pathspec
));
...
...
@@ -163,41 +198,106 @@ int git_status_foreach_ext(
diffopt
.
flags
=
diffopt
.
flags
|
GIT_DIFF_IGNORE_SUBMODULES
;
if
(
show
!=
GIT_STATUS_SHOW_WORKDIR_ONLY
)
{
err
=
git_diff_tree_to_index
(
&
head2idx
,
repo
,
head
,
NULL
,
&
diffopt
);
if
(
err
<
0
)
goto
cleanup
;
error
=
git_diff_tree_to_index
(
&
statuslist
->
head2idx
,
repo
,
head
,
NULL
,
&
diffopt
);
if
(
error
<
0
)
goto
on_error
;
}
if
(
show
!=
GIT_STATUS_SHOW_INDEX_ONLY
)
{
err
=
git_diff_index_to_workdir
(
&
idx2wd
,
repo
,
NULL
,
&
diffopt
);
if
(
err
<
0
)
goto
cleanup
;
}
error
=
git_diff_index_to_workdir
(
&
statuslist
->
idx2wd
,
repo
,
NULL
,
&
diffopt
);
usercb
.
cb
=
cb
;
usercb
.
payload
=
payload
;
usercb
.
opts
=
opts
;
if
(
error
<
0
)
goto
on_error
;
}
if
(
show
==
GIT_STATUS_SHOW_INDEX_THEN_WORKDIR
)
{
if
((
err
=
git_diff__paired_foreach
(
head2idx
,
NULL
,
status_invoke_cb
,
&
usercb
))
<
0
)
goto
cleanup
;
if
((
error
=
git_diff__paired_foreach
(
statuslist
->
head2idx
,
NULL
,
status_collect
,
statuslist
))
<
0
)
goto
on_error
;
git_diff_list_free
(
head2idx
);
head2idx
=
NULL
;
git_diff_list_free
(
statuslist
->
head2idx
);
statuslist
->
head2idx
=
NULL
;
}
err
=
git_diff__paired_foreach
(
head2idx
,
idx2wd
,
status_invoke_cb
,
&
usercb
);
if
((
error
=
git_diff__paired_foreach
(
statuslist
->
head2idx
,
statuslist
->
idx2wd
,
status_collect
,
statuslist
))
<
0
)
goto
on_error
;
*
out
=
statuslist
;
goto
done
;
on_error:
git_status_list_free
(
statuslist
);
cleanup
:
done
:
git_tree_free
(
head
);
git_diff_list_free
(
head2idx
);
git_diff_list_free
(
idx2wd
);
if
(
err
==
GIT_EUSER
)
giterr_clear
();
return
error
;
}
size_t
git_status_list_entrycount
(
git_status_list
*
statuslist
)
{
assert
(
statuslist
);
return
statuslist
->
paired
.
length
;
}
const
git_status_entry
*
git_status_byindex
(
git_status_list
*
statuslist
,
size_t
i
)
{
assert
(
statuslist
);
return
git_vector_get
(
&
statuslist
->
paired
,
i
);
}
void
git_status_list_free
(
git_status_list
*
statuslist
)
{
git_status_entry
*
status_entry
;
size_t
i
;
if
(
statuslist
==
NULL
)
return
;
git_diff_list_free
(
statuslist
->
head2idx
);
git_diff_list_free
(
statuslist
->
idx2wd
);
git_vector_foreach
(
&
statuslist
->
paired
,
i
,
status_entry
)
git__free
(
status_entry
);
return
err
;
git_vector_free
(
&
statuslist
->
paired
);
git__free
(
statuslist
);
}
int
git_status_foreach_ext
(
git_repository
*
repo
,
const
git_status_options
*
opts
,
git_status_cb
cb
,
void
*
payload
)
{
git_status_list
*
statuslist
;
const
git_status_entry
*
status_entry
;
size_t
i
;
int
error
=
0
;
if
((
error
=
git_status_list_new
(
&
statuslist
,
repo
,
opts
))
<
0
)
return
error
;
git_vector_foreach
(
&
statuslist
->
paired
,
i
,
status_entry
)
{
const
char
*
path
=
status_entry
->
head_to_index
?
status_entry
->
head_to_index
->
old_file
.
path
:
status_entry
->
index_to_workdir
->
old_file
.
path
;
if
(
cb
(
path
,
status_entry
->
status
,
payload
)
!=
0
)
{
error
=
GIT_EUSER
;
giterr_clear
();
break
;
}
}
git_status_list_free
(
statuslist
);
return
error
;
}
int
git_status_foreach
(
...
...
src/status.h
0 → 100644
View file @
1ee2ef87
/*
* Copyright (C) the libgit2 contributors. All rights reserved.
*
* This file is part of libgit2, distributed under the GNU GPL v2 with
* a Linking Exception. For full terms see the included COPYING file.
*/
#ifndef INCLUDE_status_h__
#define INCLUDE_status_h__
#include "diff.h"
#include "git2/status.h"
#include "git2/diff.h"
struct
git_status_list
{
git_status_options
opts
;
git_diff_list
*
head2idx
;
git_diff_list
*
idx2wd
;
git_vector
paired
;
};
#endif
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment