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
cbc02c10
Commit
cbc02c10
authored
Jun 28, 2012
by
Ben Straub
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #788 from nulltoken/topix/revparse
Small revparse colon syntax improvements
parents
1d8943c6
0e7af9e7
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
805 additions
and
758 deletions
+805
-758
src/revparse.c
+705
-671
tests-clar/refs/revparse.c
+100
-87
No files found.
src/revparse.c
View file @
cbc02c10
...
@@ -14,747 +14,781 @@
...
@@ -14,747 +14,781 @@
#include "git2.h"
#include "git2.h"
typedef
enum
{
typedef
enum
{
REVPARSE_STATE_INIT
,
REVPARSE_STATE_INIT
,
REVPARSE_STATE_CARET
,
REVPARSE_STATE_CARET
,
REVPARSE_STATE_LINEAR
,
REVPARSE_STATE_LINEAR
,
REVPARSE_STATE_COLON
,
REVPARSE_STATE_COLON
,
REVPARSE_STATE_DONE
,
REVPARSE_STATE_DONE
,
}
revparse_state
;
}
revparse_state
;
static
void
set_invalid_syntax_err
(
const
char
*
spec
)
static
void
set_invalid_syntax_err
(
const
char
*
spec
)
{
{
giterr_set
(
GITERR_INVALID
,
"Refspec '%s' is not valid."
,
spec
);
giterr_set
(
GITERR_INVALID
,
"Refspec '%s' is not valid."
,
spec
);
}
}
static
int
revparse_lookup_fully_qualifed_ref
(
git_object
**
out
,
git_repository
*
repo
,
const
char
*
spec
)
static
int
revparse_lookup_fully_qualifed_ref
(
git_object
**
out
,
git_repository
*
repo
,
const
char
*
spec
)
{
{
git_oid
resolved
;
git_oid
resolved
;
if
(
git_reference_name_to_oid
(
&
resolved
,
repo
,
spec
)
<
0
)
if
(
git_reference_name_to_oid
(
&
resolved
,
repo
,
spec
)
<
0
)
return
GIT_ERROR
;
return
GIT_ERROR
;
return
git_object_lookup
(
out
,
repo
,
&
resolved
,
GIT_OBJ_ANY
);
return
git_object_lookup
(
out
,
repo
,
&
resolved
,
GIT_OBJ_ANY
);
}
}
/* Returns non-zero if yes */
/* Returns non-zero if yes */
static
int
spec_looks_like_describe_output
(
const
char
*
spec
)
static
int
spec_looks_like_describe_output
(
const
char
*
spec
)
{
{
regex_t
regex
;
regex_t
regex
;
int
regex_error
,
retcode
;
int
regex_error
,
retcode
;
regex_error
=
regcomp
(
&
regex
,
".+-[0-9]+-g[0-9a-fA-F]+"
,
REG_EXTENDED
);
regex_error
=
regcomp
(
&
regex
,
".+-[0-9]+-g[0-9a-fA-F]+"
,
REG_EXTENDED
);
if
(
regex_error
!=
0
)
{
if
(
regex_error
!=
0
)
{
giterr_set_regex
(
&
regex
,
regex_error
);
giterr_set_regex
(
&
regex
,
regex_error
);
return
1
;
/* To be safe */
return
1
;
/* To be safe */
}
}
retcode
=
regexec
(
&
regex
,
spec
,
0
,
NULL
,
0
);
retcode
=
regexec
(
&
regex
,
spec
,
0
,
NULL
,
0
);
regfree
(
&
regex
);
regfree
(
&
regex
);
return
retcode
==
0
;
return
retcode
==
0
;
}
}
static
int
revparse_lookup_object
(
git_object
**
out
,
git_repository
*
repo
,
const
char
*
spec
)
static
int
revparse_lookup_object
(
git_object
**
out
,
git_repository
*
repo
,
const
char
*
spec
)
{
{
size_t
speclen
=
strlen
(
spec
);
size_t
speclen
=
strlen
(
spec
);
git_object
*
obj
=
NULL
;
git_object
*
obj
=
NULL
;
git_oid
oid
;
git_oid
oid
;
git_buf
refnamebuf
=
GIT_BUF_INIT
;
git_buf
refnamebuf
=
GIT_BUF_INIT
;
static
const
char
*
formatters
[]
=
{
static
const
char
*
formatters
[]
=
{
"refs/%s"
,
"refs/%s"
,
"refs/tags/%s"
,
"refs/tags/%s"
,
"refs/heads/%s"
,
"refs/heads/%s"
,
"refs/remotes/%s"
,
"refs/remotes/%s"
,
"refs/remotes/%s/HEAD"
,
"refs/remotes/%s/HEAD"
,
NULL
NULL
};
};
unsigned
int
i
;
unsigned
int
i
;
const
char
*
substr
;
const
char
*
substr
;
/* "git describe" output; snip everything before/including "-g" */
/* "git describe" output; snip everything before/including "-g" */
substr
=
strstr
(
spec
,
"-g"
);
substr
=
strstr
(
spec
,
"-g"
);
if
(
substr
&&
if
(
substr
&&
spec_looks_like_describe_output
(
spec
)
&&
spec_looks_like_describe_output
(
spec
)
&&
!
revparse_lookup_object
(
out
,
repo
,
substr
+
2
))
{
!
revparse_lookup_object
(
out
,
repo
,
substr
+
2
))
{
return
0
;
return
0
;
}
}
/* SHA or prefix */
/* SHA or prefix */
if
(
!
git_oid_fromstrn
(
&
oid
,
spec
,
speclen
))
{
if
(
!
git_oid_fromstrn
(
&
oid
,
spec
,
speclen
))
{
if
(
!
git_object_lookup_prefix
(
&
obj
,
repo
,
&
oid
,
speclen
,
GIT_OBJ_ANY
))
{
if
(
!
git_object_lookup_prefix
(
&
obj
,
repo
,
&
oid
,
speclen
,
GIT_OBJ_ANY
))
{
*
out
=
obj
;
*
out
=
obj
;
return
0
;
return
0
;
}
}
}
}
/* Fully-named ref */
/* Fully-named ref */
if
(
!
revparse_lookup_fully_qualifed_ref
(
&
obj
,
repo
,
spec
))
{
if
(
!
revparse_lookup_fully_qualifed_ref
(
&
obj
,
repo
,
spec
))
{
*
out
=
obj
;
*
out
=
obj
;
return
0
;
return
0
;
}
}
/* Partially-named ref; match in this order: */
/* Partially-named ref; match in this order: */
for
(
i
=
0
;
formatters
[
i
];
i
++
)
{
for
(
i
=
0
;
formatters
[
i
];
i
++
)
{
git_buf_clear
(
&
refnamebuf
);
git_buf_clear
(
&
refnamebuf
);
if
(
git_buf_printf
(
&
refnamebuf
,
formatters
[
i
],
spec
)
<
0
)
{
if
(
git_buf_printf
(
&
refnamebuf
,
formatters
[
i
],
spec
)
<
0
)
{
return
GIT_ERROR
;
return
GIT_ERROR
;
}
}
if
(
!
revparse_lookup_fully_qualifed_ref
(
&
obj
,
repo
,
git_buf_cstr
(
&
refnamebuf
)))
{
if
(
!
revparse_lookup_fully_qualifed_ref
(
&
obj
,
repo
,
git_buf_cstr
(
&
refnamebuf
)))
{
git_buf_free
(
&
refnamebuf
);
git_buf_free
(
&
refnamebuf
);
*
out
=
obj
;
*
out
=
obj
;
return
0
;
return
0
;
}
}
}
}
git_buf_free
(
&
refnamebuf
);
git_buf_free
(
&
refnamebuf
);
giterr_set
(
GITERR_REFERENCE
,
"Refspec '%s' not found."
,
spec
);
giterr_set
(
GITERR_REFERENCE
,
"Refspec '%s' not found."
,
spec
);
return
GIT_ERROR
;
return
GIT_ERROR
;
}
}
static
int
all_chars_are_digits
(
const
char
*
str
,
size_t
len
)
static
int
all_chars_are_digits
(
const
char
*
str
,
size_t
len
)
{
{
size_t
i
=
0
;
size_t
i
=
0
;
for
(
i
=
0
;
i
<
len
;
i
++
)
{
for
(
i
=
0
;
i
<
len
;
i
++
)
{
if
(
str
[
i
]
<
'0'
||
str
[
i
]
>
'9'
)
return
0
;
if
(
str
[
i
]
<
'0'
||
str
[
i
]
>
'9'
)
return
0
;
}
}
return
1
;
return
1
;
}
}
static
void
normalize_maybe_empty_refname
(
git_buf
*
buf
,
git_repository
*
repo
,
const
char
*
refspec
,
size_t
refspeclen
)
static
void
normalize_maybe_empty_refname
(
git_buf
*
buf
,
git_repository
*
repo
,
const
char
*
refspec
,
size_t
refspeclen
)
{
{
git_reference
*
ref
;
git_reference
*
ref
;
if
(
!
refspeclen
)
{
if
(
!
refspeclen
)
{
/* Empty refspec means current branch (target of HEAD) */
/* Empty refspec means current branch (target of HEAD) */
git_reference_lookup
(
&
ref
,
repo
,
"HEAD"
);
git_reference_lookup
(
&
ref
,
repo
,
"HEAD"
);
git_buf_puts
(
buf
,
git_reference_target
(
ref
));
git_buf_puts
(
buf
,
git_reference_target
(
ref
));
git_reference_free
(
ref
);
git_reference_free
(
ref
);
}
else
if
(
strstr
(
refspec
,
"HEAD"
))
{
}
else
if
(
strstr
(
refspec
,
"HEAD"
))
{
/* Explicit head */
/* Explicit head */
git_buf_puts
(
buf
,
refspec
);
git_buf_puts
(
buf
,
refspec
);
}
else
{
}
else
{
if
(
git__prefixcmp
(
refspec
,
"refs/heads/"
)
!=
0
)
{
if
(
git__prefixcmp
(
refspec
,
"refs/heads/"
)
!=
0
)
{
git_buf_printf
(
buf
,
"refs/heads/%s"
,
refspec
);
git_buf_printf
(
buf
,
"refs/heads/%s"
,
refspec
);
}
else
{
}
else
{
git_buf_puts
(
buf
,
refspec
);
git_buf_puts
(
buf
,
refspec
);
}
}
}
}
}
}
static
int
walk_ref_history
(
git_object
**
out
,
git_repository
*
repo
,
const
char
*
refspec
,
const
char
*
reflogspec
)
static
int
walk_ref_history
(
git_object
**
out
,
git_repository
*
repo
,
const
char
*
refspec
,
const
char
*
reflogspec
)
{
{
git_reference
*
ref
;
git_reference
*
ref
;
git_reflog
*
reflog
=
NULL
;
git_reflog
*
reflog
=
NULL
;
int
n
,
retcode
=
GIT_ERROR
;
int
n
,
retcode
=
GIT_ERROR
;
int
i
,
refloglen
;
int
i
,
refloglen
;
const
git_reflog_entry
*
entry
;
const
git_reflog_entry
*
entry
;
git_buf
buf
=
GIT_BUF_INIT
;
git_buf
buf
=
GIT_BUF_INIT
;
size_t
refspeclen
=
strlen
(
refspec
);
size_t
refspeclen
=
strlen
(
refspec
);
size_t
reflogspeclen
=
strlen
(
reflogspec
);
size_t
reflogspeclen
=
strlen
(
reflogspec
);
if
(
git__prefixcmp
(
reflogspec
,
"@{"
)
!=
0
||
if
(
git__prefixcmp
(
reflogspec
,
"@{"
)
!=
0
||
git__suffixcmp
(
reflogspec
,
"}"
)
!=
0
)
{
git__suffixcmp
(
reflogspec
,
"}"
)
!=
0
)
{
giterr_set
(
GITERR_INVALID
,
"Bad reflogspec '%s'"
,
reflogspec
);
giterr_set
(
GITERR_INVALID
,
"Bad reflogspec '%s'"
,
reflogspec
);
return
GIT_ERROR
;
return
GIT_ERROR
;
}
}
/* "@{-N}" form means walk back N checkouts. That means the HEAD log. */
/* "@{-N}" form means walk back N checkouts. That means the HEAD log. */
if
(
refspeclen
==
0
&&
!
git__prefixcmp
(
reflogspec
,
"@{-"
))
{
if
(
refspeclen
==
0
&&
!
git__prefixcmp
(
reflogspec
,
"@{-"
))
{
regex_t
regex
;
regex_t
regex
;
int
regex_error
;
int
regex_error
;
if
(
git__strtol32
(
&
n
,
reflogspec
+
3
,
NULL
,
0
)
<
0
||
if
(
git__strtol32
(
&
n
,
reflogspec
+
3
,
NULL
,
0
)
<
0
||
n
<
1
)
{
n
<
1
)
{
giterr_set
(
GITERR_INVALID
,
"Invalid reflogspec %s"
,
reflogspec
);
giterr_set
(
GITERR_INVALID
,
"Invalid reflogspec %s"
,
reflogspec
);
return
GIT_ERROR
;
return
GIT_ERROR
;
}
}
if
(
!
git_reference_lookup
(
&
ref
,
repo
,
"HEAD"
))
{
if
(
!
git_reference_lookup
(
&
ref
,
repo
,
"HEAD"
))
{
if
(
!
git_reflog_read
(
&
reflog
,
ref
))
{
if
(
!
git_reflog_read
(
&
reflog
,
ref
))
{
regex_error
=
regcomp
(
&
regex
,
"checkout: moving from (.*) to .*"
,
REG_EXTENDED
);
regex_error
=
regcomp
(
&
regex
,
"checkout: moving from (.*) to .*"
,
REG_EXTENDED
);
if
(
regex_error
!=
0
)
{
if
(
regex_error
!=
0
)
{
giterr_set_regex
(
&
regex
,
regex_error
);
giterr_set_regex
(
&
regex
,
regex_error
);
}
else
{
}
else
{
regmatch_t
regexmatches
[
2
];
regmatch_t
regexmatches
[
2
];
refloglen
=
git_reflog_entrycount
(
reflog
);
refloglen
=
git_reflog_entrycount
(
reflog
);
for
(
i
=
refloglen
-
1
;
i
>=
0
;
i
--
)
{
for
(
i
=
refloglen
-
1
;
i
>=
0
;
i
--
)
{
const
char
*
msg
;
const
char
*
msg
;
entry
=
git_reflog_entry_byindex
(
reflog
,
i
);
entry
=
git_reflog_entry_byindex
(
reflog
,
i
);
msg
=
git_reflog_entry_msg
(
entry
);
msg
=
git_reflog_entry_msg
(
entry
);
if
(
!
regexec
(
&
regex
,
msg
,
2
,
regexmatches
,
0
))
{
if
(
!
regexec
(
&
regex
,
msg
,
2
,
regexmatches
,
0
))
{
n
--
;
n
--
;
if
(
!
n
)
{
if
(
!
n
)
{
git_buf_put
(
&
buf
,
msg
+
regexmatches
[
1
].
rm_so
,
regexmatches
[
1
].
rm_eo
-
regexmatches
[
1
].
rm_so
);
git_buf_put
(
&
buf
,
msg
+
regexmatches
[
1
].
rm_so
,
regexmatches
[
1
].
rm_eo
-
regexmatches
[
1
].
rm_so
);
retcode
=
revparse_lookup_object
(
out
,
repo
,
git_buf_cstr
(
&
buf
));
retcode
=
revparse_lookup_object
(
out
,
repo
,
git_buf_cstr
(
&
buf
));
break
;
break
;
}
}
}
}
}
}
regfree
(
&
regex
);
regfree
(
&
regex
);
}
}
}
}
git_reference_free
(
ref
);
git_reference_free
(
ref
);
}
}
}
else
{
}
else
{
int
date_error
=
0
;
int
date_error
=
0
;
git_time_t
timestamp
;
git_time_t
timestamp
;
git_buf
datebuf
=
GIT_BUF_INIT
;
git_buf
datebuf
=
GIT_BUF_INIT
;
git_buf_put
(
&
datebuf
,
reflogspec
+
2
,
reflogspeclen
-
3
);
git_buf_put
(
&
datebuf
,
reflogspec
+
2
,
reflogspeclen
-
3
);
date_error
=
git__date_parse
(
&
timestamp
,
git_buf_cstr
(
&
datebuf
));
date_error
=
git__date_parse
(
&
timestamp
,
git_buf_cstr
(
&
datebuf
));
/* @{u} or @{upstream} -> upstream branch, for a tracking branch. This is stored in the config. */
/* @{u} or @{upstream} -> upstream branch, for a tracking branch. This is stored in the config. */
if
(
!
strcmp
(
reflogspec
,
"@{u}"
)
||
!
strcmp
(
reflogspec
,
"@{upstream}"
))
{
if
(
!
strcmp
(
reflogspec
,
"@{u}"
)
||
!
strcmp
(
reflogspec
,
"@{upstream}"
))
{
git_config
*
cfg
;
git_config
*
cfg
;
if
(
!
git_repository_config
(
&
cfg
,
repo
))
{
if
(
!
git_repository_config
(
&
cfg
,
repo
))
{
/* Is the ref a tracking branch? */
/* Is the ref a tracking branch? */
const
char
*
remote
;
const
char
*
remote
;
git_buf_clear
(
&
buf
);
git_buf_clear
(
&
buf
);
git_buf_printf
(
&
buf
,
"branch.%s.remote"
,
refspec
);
git_buf_printf
(
&
buf
,
"branch.%s.remote"
,
refspec
);
if
(
!
git_config_get_string
(
&
remote
,
cfg
,
git_buf_cstr
(
&
buf
)))
{
if
(
!
git_config_get_string
(
&
remote
,
cfg
,
git_buf_cstr
(
&
buf
)))
{
/* Yes. Find the first merge target name. */
/* Yes. Find the first merge target name. */
const
char
*
mergetarget
;
const
char
*
mergetarget
;
git_buf_clear
(
&
buf
);
git_buf_clear
(
&
buf
);
git_buf_printf
(
&
buf
,
"branch.%s.merge"
,
refspec
);
git_buf_printf
(
&
buf
,
"branch.%s.merge"
,
refspec
);
if
(
!
git_config_get_string
(
&
mergetarget
,
cfg
,
git_buf_cstr
(
&
buf
))
&&
if
(
!
git_config_get_string
(
&
mergetarget
,
cfg
,
git_buf_cstr
(
&
buf
))
&&
!
git__prefixcmp
(
mergetarget
,
"refs/heads/"
))
{
!
git__prefixcmp
(
mergetarget
,
"refs/heads/"
))
{
/* Success. Look up the target and fetch the object. */
/* Success. Look up the target and fetch the object. */
git_buf_clear
(
&
buf
);
git_buf_clear
(
&
buf
);
git_buf_printf
(
&
buf
,
"refs/remotes/%s/%s"
,
remote
,
mergetarget
+
11
);
git_buf_printf
(
&
buf
,
"refs/remotes/%s/%s"
,
remote
,
mergetarget
+
11
);
retcode
=
revparse_lookup_fully_qualifed_ref
(
out
,
repo
,
git_buf_cstr
(
&
buf
));
retcode
=
revparse_lookup_fully_qualifed_ref
(
out
,
repo
,
git_buf_cstr
(
&
buf
));
}
}
}
}
git_config_free
(
cfg
);
git_config_free
(
cfg
);
}
}
}
}
/* @{N} -> Nth prior value for the ref (from reflog) */
/* @{N} -> Nth prior value for the ref (from reflog) */
else
if
(
all_chars_are_digits
(
reflogspec
+
2
,
reflogspeclen
-
3
)
&&
else
if
(
all_chars_are_digits
(
reflogspec
+
2
,
reflogspeclen
-
3
)
&&
!
git__strtol32
(
&
n
,
reflogspec
+
2
,
NULL
,
0
)
&&
!
git__strtol32
(
&
n
,
reflogspec
+
2
,
NULL
,
0
)
&&
n
<=
100000000
)
{
/* Allow integer time */
n
<=
100000000
)
{
/* Allow integer time */
normalize_maybe_empty_refname
(
&
buf
,
repo
,
refspec
,
refspeclen
);
normalize_maybe_empty_refname
(
&
buf
,
repo
,
refspec
,
refspeclen
);
if
(
n
==
0
)
{
if
(
n
==
0
)
{
retcode
=
revparse_lookup_fully_qualifed_ref
(
out
,
repo
,
git_buf_cstr
(
&
buf
));
retcode
=
revparse_lookup_fully_qualifed_ref
(
out
,
repo
,
git_buf_cstr
(
&
buf
));
}
else
if
(
!
git_reference_lookup
(
&
ref
,
repo
,
git_buf_cstr
(
&
buf
)))
{
}
else
if
(
!
git_reference_lookup
(
&
ref
,
repo
,
git_buf_cstr
(
&
buf
)))
{
if
(
!
git_reflog_read
(
&
reflog
,
ref
))
{
if
(
!
git_reflog_read
(
&
reflog
,
ref
))
{
int
numentries
=
git_reflog_entrycount
(
reflog
);
int
numentries
=
git_reflog_entrycount
(
reflog
);
if
(
numentries
<
n
)
{
if
(
numentries
<
n
)
{
giterr_set
(
GITERR_REFERENCE
,
"Reflog for '%s' has only %d entries, asked for %d"
,
giterr_set
(
GITERR_REFERENCE
,
"Reflog for '%s' has only %d entries, asked for %d"
,
git_buf_cstr
(
&
buf
),
numentries
,
n
);
git_buf_cstr
(
&
buf
),
numentries
,
n
);
retcode
=
GIT_ERROR
;
retcode
=
GIT_ERROR
;
}
else
{
}
else
{
const
git_reflog_entry
*
entry
=
git_reflog_entry_byindex
(
reflog
,
n
);
const
git_reflog_entry
*
entry
=
git_reflog_entry_byindex
(
reflog
,
n
);
const
git_oid
*
oid
=
git_reflog_entry_oidold
(
entry
);
const
git_oid
*
oid
=
git_reflog_entry_oidold
(
entry
);
retcode
=
git_object_lookup
(
out
,
repo
,
oid
,
GIT_OBJ_ANY
);
retcode
=
git_object_lookup
(
out
,
repo
,
oid
,
GIT_OBJ_ANY
);
}
}
}
}
git_reference_free
(
ref
);
git_reference_free
(
ref
);
}
}
}
}
else
if
(
!
date_error
)
{
else
if
(
!
date_error
)
{
/* Ref as it was on a certain date */
/* Ref as it was on a certain date */
normalize_maybe_empty_refname
(
&
buf
,
repo
,
refspec
,
refspeclen
);
normalize_maybe_empty_refname
(
&
buf
,
repo
,
refspec
,
refspeclen
);
if
(
!
git_reference_lookup
(
&
ref
,
repo
,
git_buf_cstr
(
&
buf
)))
{
if
(
!
git_reference_lookup
(
&
ref
,
repo
,
git_buf_cstr
(
&
buf
)))
{
git_reflog
*
reflog
;
git_reflog
*
reflog
;
if
(
!
git_reflog_read
(
&
reflog
,
ref
))
{
if
(
!
git_reflog_read
(
&
reflog
,
ref
))
{
/* Keep walking until we find an entry older than the given date */
/* Keep walking until we find an entry older than the given date */
int
numentries
=
git_reflog_entrycount
(
reflog
);
int
numentries
=
git_reflog_entrycount
(
reflog
);
int
i
;
int
i
;
/* TODO: clunky. Factor "now" into a utility */
/* TODO: clunky. Factor "now" into a utility */
git_signature
*
sig
;
git_signature
*
sig
;
git_time
as_of
;
git_time
as_of
;
git_signature_now
(
&
sig
,
"blah"
,
"blah"
);
git_signature_now
(
&
sig
,
"blah"
,
"blah"
);
as_of
=
sig
->
when
;
as_of
=
sig
->
when
;
git_signature_free
(
sig
);
git_signature_free
(
sig
);
as_of
.
time
=
(
timestamp
>
0
)
as_of
.
time
=
(
timestamp
>
0
)
?
timestamp
?
timestamp
:
sig
->
when
.
time
+
timestamp
;
:
sig
->
when
.
time
+
timestamp
;
for
(
i
=
numentries
-
1
;
i
>
0
;
i
--
)
{
for
(
i
=
numentries
-
1
;
i
>
0
;
i
--
)
{
const
git_reflog_entry
*
entry
=
git_reflog_entry_byindex
(
reflog
,
i
);
const
git_reflog_entry
*
entry
=
git_reflog_entry_byindex
(
reflog
,
i
);
git_time
commit_time
=
git_reflog_entry_committer
(
entry
)
->
when
;
git_time
commit_time
=
git_reflog_entry_committer
(
entry
)
->
when
;
if
(
git__time_cmp
(
&
commit_time
,
&
as_of
)
<=
0
)
{
if
(
git__time_cmp
(
&
commit_time
,
&
as_of
)
<=
0
)
{
retcode
=
git_object_lookup
(
out
,
repo
,
git_reflog_entry_oidnew
(
entry
),
GIT_OBJ_ANY
);
retcode
=
git_object_lookup
(
out
,
repo
,
git_reflog_entry_oidnew
(
entry
),
GIT_OBJ_ANY
);
break
;
break
;
}
}
}
}
if
(
!
i
)
{
if
(
!
i
)
{
/* Didn't find a match. Use the oldest revision in the reflog. */
/* Didn't find a match. Use the oldest revision in the reflog. */
const
git_reflog_entry
*
entry
=
git_reflog_entry_byindex
(
reflog
,
0
);
const
git_reflog_entry
*
entry
=
git_reflog_entry_byindex
(
reflog
,
0
);
retcode
=
git_object_lookup
(
out
,
repo
,
git_reflog_entry_oidnew
(
entry
),
GIT_OBJ_ANY
);
retcode
=
git_object_lookup
(
out
,
repo
,
git_reflog_entry_oidnew
(
entry
),
GIT_OBJ_ANY
);
}
}
git_reflog_free
(
reflog
);
git_reflog_free
(
reflog
);
}
}
git_reference_free
(
ref
);
git_reference_free
(
ref
);
}
}
}
}
git_buf_free
(
&
datebuf
);
git_buf_free
(
&
datebuf
);
}
}
if
(
reflog
)
git_reflog_free
(
reflog
);
if
(
reflog
)
git_reflog_free
(
reflog
);
git_buf_free
(
&
buf
);
git_buf_free
(
&
buf
);
return
retcode
;
return
retcode
;
}
}
static
git_object
*
dereference_object
(
git_object
*
obj
)
static
git_object
*
dereference_object
(
git_object
*
obj
)
{
{
git_otype
type
=
git_object_type
(
obj
);
git_otype
type
=
git_object_type
(
obj
);
switch
(
type
)
{
switch
(
type
)
{
case
GIT_OBJ_COMMIT
:
case
GIT_OBJ_COMMIT
:
{
{
git_tree
*
tree
=
NULL
;
git_tree
*
tree
=
NULL
;
if
(
0
==
git_commit_tree
(
&
tree
,
(
git_commit
*
)
obj
))
{
if
(
0
==
git_commit_tree
(
&
tree
,
(
git_commit
*
)
obj
))
{
return
(
git_object
*
)
tree
;
return
(
git_object
*
)
tree
;
}
}
}
}
break
;
break
;
case
GIT_OBJ_TAG
:
case
GIT_OBJ_TAG
:
{
{
git_object
*
newobj
=
NULL
;
git_object
*
newobj
=
NULL
;
if
(
0
==
git_tag_target
(
&
newobj
,
(
git_tag
*
)
obj
))
{
if
(
0
==
git_tag_target
(
&
newobj
,
(
git_tag
*
)
obj
))
{
return
newobj
;
return
newobj
;
}
}
}
}
break
;
break
;
default:
default:
case
GIT_OBJ_TREE
:
case
GIT_OBJ_TREE
:
case
GIT_OBJ_BLOB
:
case
GIT_OBJ_BLOB
:
case
GIT_OBJ_OFS_DELTA
:
case
GIT_OBJ_OFS_DELTA
:
case
GIT_OBJ_REF_DELTA
:
case
GIT_OBJ_REF_DELTA
:
break
;
break
;
}
}
/* Can't dereference some types */
/* Can't dereference some types */
return
NULL
;
return
NULL
;
}
}
static
int
dereference_to_type
(
git_object
**
out
,
git_object
*
obj
,
git_otype
target_type
)
static
int
dereference_to_type
(
git_object
**
out
,
git_object
*
obj
,
git_otype
target_type
)
{
{
int
retcode
=
1
;
int
retcode
=
1
;
git_object
*
obj1
=
obj
,
*
obj2
=
obj
;
git_object
*
obj1
=
obj
,
*
obj2
=
obj
;
while
(
retcode
>
0
)
{
while
(
retcode
>
0
)
{
git_otype
this_type
=
git_object_type
(
obj1
);
git_otype
this_type
=
git_object_type
(
obj1
);
if
(
this_type
==
target_type
)
{
if
(
this_type
==
target_type
)
{
*
out
=
obj1
;
*
out
=
obj1
;
retcode
=
0
;
retcode
=
0
;
}
else
{
}
else
{
/* Dereference once, if possible. */
/* Dereference once, if possible. */
obj2
=
dereference_object
(
obj1
);
obj2
=
dereference_object
(
obj1
);
if
(
!
obj2
)
{
if
(
!
obj2
)
{
giterr_set
(
GITERR_REFERENCE
,
"Can't dereference to type"
);
giterr_set
(
GITERR_REFERENCE
,
"Can't dereference to type"
);
retcode
=
GIT_ERROR
;
retcode
=
GIT_ERROR
;
}
}
}
}
if
(
obj1
!=
obj
&&
obj1
!=
obj2
)
{
if
(
obj1
!=
obj
&&
obj1
!=
obj2
)
{
git_object_free
(
obj1
);
git_object_free
(
obj1
);
}
}
obj1
=
obj2
;
obj1
=
obj2
;
}
}
return
retcode
;
return
retcode
;
}
}
static
git_otype
parse_obj_type
(
const
char
*
str
)
static
git_otype
parse_obj_type
(
const
char
*
str
)
{
{
if
(
!
strcmp
(
str
,
"{commit}"
))
return
GIT_OBJ_COMMIT
;
if
(
!
strcmp
(
str
,
"{commit}"
))
return
GIT_OBJ_COMMIT
;
if
(
!
strcmp
(
str
,
"{tree}"
))
return
GIT_OBJ_TREE
;
if
(
!
strcmp
(
str
,
"{tree}"
))
return
GIT_OBJ_TREE
;
if
(
!
strcmp
(
str
,
"{blob}"
))
return
GIT_OBJ_BLOB
;
if
(
!
strcmp
(
str
,
"{blob}"
))
return
GIT_OBJ_BLOB
;
if
(
!
strcmp
(
str
,
"{tag}"
))
return
GIT_OBJ_TAG
;
if
(
!
strcmp
(
str
,
"{tag}"
))
return
GIT_OBJ_TAG
;
return
GIT_OBJ_BAD
;
return
GIT_OBJ_BAD
;
}
}
static
int
handle_caret_syntax
(
git_object
**
out
,
git_repository
*
repo
,
git_object
*
obj
,
const
char
*
movement
)
static
int
handle_caret_syntax
(
git_object
**
out
,
git_repository
*
repo
,
git_object
*
obj
,
const
char
*
movement
)
{
{
git_commit
*
commit
;
git_commit
*
commit
;
size_t
movementlen
=
strlen
(
movement
);
size_t
movementlen
=
strlen
(
movement
);
int
n
;
int
n
;
if
(
*
movement
==
'{'
)
{
if
(
*
movement
==
'{'
)
{
if
(
movement
[
movementlen
-
1
]
!=
'}'
)
{
if
(
movement
[
movementlen
-
1
]
!=
'}'
)
{
set_invalid_syntax_err
(
movement
);
set_invalid_syntax_err
(
movement
);
return
GIT_ERROR
;
return
GIT_ERROR
;
}
}
/* {} -> Dereference until we reach an object that isn't a tag. */
/* {} -> Dereference until we reach an object that isn't a tag. */
if
(
movementlen
==
2
)
{
if
(
movementlen
==
2
)
{
git_object
*
newobj
=
obj
;
git_object
*
newobj
=
obj
;
git_object
*
newobj2
=
newobj
;
git_object
*
newobj2
=
newobj
;
while
(
git_object_type
(
newobj2
)
==
GIT_OBJ_TAG
)
{
while
(
git_object_type
(
newobj2
)
==
GIT_OBJ_TAG
)
{
newobj2
=
dereference_object
(
newobj
);
newobj2
=
dereference_object
(
newobj
);
if
(
newobj
!=
obj
)
git_object_free
(
newobj
);
if
(
newobj
!=
obj
)
git_object_free
(
newobj
);
if
(
!
newobj2
)
{
if
(
!
newobj2
)
{
giterr_set
(
GITERR_REFERENCE
,
"Couldn't find object of target type."
);
giterr_set
(
GITERR_REFERENCE
,
"Couldn't find object of target type."
);
return
GIT_ERROR
;
return
GIT_ERROR
;
}
}
newobj
=
newobj2
;
newobj
=
newobj2
;
}
}
*
out
=
newobj2
;
*
out
=
newobj2
;
return
0
;
return
0
;
}
}
/* {/...} -> Walk all commits until we see a commit msg that matches the phrase. */
/* {/...} -> Walk all commits until we see a commit msg that matches the phrase. */
if
(
movement
[
1
]
==
'/'
)
{
if
(
movement
[
1
]
==
'/'
)
{
int
retcode
=
GIT_ERROR
;
int
retcode
=
GIT_ERROR
;
git_revwalk
*
walk
;
git_revwalk
*
walk
;
if
(
!
git_revwalk_new
(
&
walk
,
repo
))
{
if
(
!
git_revwalk_new
(
&
walk
,
repo
))
{
git_oid
oid
;
git_oid
oid
;
regex_t
preg
;
regex_t
preg
;
int
reg_error
;
int
reg_error
;
git_buf
buf
=
GIT_BUF_INIT
;
git_buf
buf
=
GIT_BUF_INIT
;
git_revwalk_sorting
(
walk
,
GIT_SORT_TIME
);
git_revwalk_sorting
(
walk
,
GIT_SORT_TIME
);
git_revwalk_push
(
walk
,
git_object_id
(
obj
));
git_revwalk_push
(
walk
,
git_object_id
(
obj
));
/* Extract the regex from the movement string */
/* Extract the regex from the movement string */
git_buf_put
(
&
buf
,
movement
+
2
,
strlen
(
movement
)
-
3
);
git_buf_put
(
&
buf
,
movement
+
2
,
strlen
(
movement
)
-
3
);
reg_error
=
regcomp
(
&
preg
,
git_buf_cstr
(
&
buf
),
REG_EXTENDED
);
reg_error
=
regcomp
(
&
preg
,
git_buf_cstr
(
&
buf
),
REG_EXTENDED
);
if
(
reg_error
!=
0
)
{
if
(
reg_error
!=
0
)
{
giterr_set_regex
(
&
preg
,
reg_error
);
giterr_set_regex
(
&
preg
,
reg_error
);
}
else
{
}
else
{
while
(
!
git_revwalk_next
(
&
oid
,
walk
))
{
while
(
!
git_revwalk_next
(
&
oid
,
walk
))
{
git_object
*
walkobj
;
git_object
*
walkobj
;
/* Fetch the commit object, and check for matches in the message */
/* Fetch the commit object, and check for matches in the message */
if
(
!
git_object_lookup
(
&
walkobj
,
repo
,
&
oid
,
GIT_OBJ_COMMIT
))
{
if
(
!
git_object_lookup
(
&
walkobj
,
repo
,
&
oid
,
GIT_OBJ_COMMIT
))
{
if
(
!
regexec
(
&
preg
,
git_commit_message
((
git_commit
*
)
walkobj
),
0
,
NULL
,
0
))
{
if
(
!
regexec
(
&
preg
,
git_commit_message
((
git_commit
*
)
walkobj
),
0
,
NULL
,
0
))
{
/* Found it! */
/* Found it! */
retcode
=
0
;
retcode
=
0
;
*
out
=
walkobj
;
*
out
=
walkobj
;
if
(
obj
==
walkobj
)
{
if
(
obj
==
walkobj
)
{
/* Avoid leaking an object */
/* Avoid leaking an object */
git_object_free
(
walkobj
);
git_object_free
(
walkobj
);
}
}
break
;
break
;
}
}
git_object_free
(
walkobj
);
git_object_free
(
walkobj
);
}
}
}
}
if
(
retcode
<
0
)
{
if
(
retcode
<
0
)
{
giterr_set
(
GITERR_REFERENCE
,
"Couldn't find a match for %s"
,
movement
);
giterr_set
(
GITERR_REFERENCE
,
"Couldn't find a match for %s"
,
movement
);
}
}
regfree
(
&
preg
);
regfree
(
&
preg
);
}
}
git_buf_free
(
&
buf
);
git_buf_free
(
&
buf
);
git_revwalk_free
(
walk
);
git_revwalk_free
(
walk
);
}
}
return
retcode
;
return
retcode
;
}
}
/* {...} -> Dereference until we reach an object of a certain type. */
/* {...} -> Dereference until we reach an object of a certain type. */
if
(
dereference_to_type
(
out
,
obj
,
parse_obj_type
(
movement
))
<
0
)
{
if
(
dereference_to_type
(
out
,
obj
,
parse_obj_type
(
movement
))
<
0
)
{
return
GIT_ERROR
;
return
GIT_ERROR
;
}
}
return
0
;
return
0
;
}
}
/* Dereference until we reach a commit. */
/* Dereference until we reach a commit. */
if
(
dereference_to_type
(
&
obj
,
obj
,
GIT_OBJ_COMMIT
)
<
0
)
{
if
(
dereference_to_type
(
&
obj
,
obj
,
GIT_OBJ_COMMIT
)
<
0
)
{
/* Can't dereference to a commit; fail */
/* Can't dereference to a commit; fail */
return
GIT_ERROR
;
return
GIT_ERROR
;
}
}
/* "^" is the same as "^1" */
/* "^" is the same as "^1" */
if
(
movementlen
==
0
)
{
if
(
movementlen
==
0
)
{
n
=
1
;
n
=
1
;
}
else
{
}
else
{
git__strtol32
(
&
n
,
movement
,
NULL
,
0
);
git__strtol32
(
&
n
,
movement
,
NULL
,
0
);
}
}
commit
=
(
git_commit
*
)
obj
;
commit
=
(
git_commit
*
)
obj
;
/* "^0" just returns the input */
/* "^0" just returns the input */
if
(
n
==
0
)
{
if
(
n
==
0
)
{
*
out
=
obj
;
*
out
=
obj
;
return
0
;
return
0
;
}
}
if
(
git_commit_parent
(
&
commit
,
commit
,
n
-
1
)
<
0
)
{
if
(
git_commit_parent
(
&
commit
,
commit
,
n
-
1
)
<
0
)
{
return
GIT_ERROR
;
return
GIT_ENOTFOUND
;
}
}
*
out
=
(
git_object
*
)
commit
;
*
out
=
(
git_object
*
)
commit
;
return
0
;
return
0
;
}
}
static
int
handle_linear_syntax
(
git_object
**
out
,
git_object
*
obj
,
const
char
*
movement
)
static
int
handle_linear_syntax
(
git_object
**
out
,
git_object
*
obj
,
const
char
*
movement
)
{
{
git_commit
*
commit1
,
*
commit2
;
git_commit
*
commit1
,
*
commit2
;
int
i
,
n
;
int
i
,
n
;
/* Dereference until we reach a commit. */
/* Dereference until we reach a commit. */
if
(
dereference_to_type
(
&
obj
,
obj
,
GIT_OBJ_COMMIT
)
<
0
)
{
if
(
dereference_to_type
(
&
obj
,
obj
,
GIT_OBJ_COMMIT
)
<
0
)
{
/* Can't dereference to a commit; fail */
/* Can't dereference to a commit; fail */
return
GIT_ERROR
;
return
GIT_ERROR
;
}
}
/* "~" is the same as "~1" */
/* "~" is the same as "~1" */
if
(
*
movement
==
'\0'
)
{
if
(
*
movement
==
'\0'
)
{
n
=
1
;
n
=
1
;
}
else
if
(
git__strtol32
(
&
n
,
movement
,
NULL
,
0
)
<
0
)
{
}
else
if
(
git__strtol32
(
&
n
,
movement
,
NULL
,
0
)
<
0
)
{
return
GIT_ERROR
;
return
GIT_ERROR
;
}
}
commit1
=
(
git_commit
*
)
obj
;
commit1
=
(
git_commit
*
)
obj
;
/* "~0" just returns the input */
/* "~0" just returns the input */
if
(
n
==
0
)
{
if
(
n
==
0
)
{
*
out
=
obj
;
*
out
=
obj
;
return
0
;
return
0
;
}
}
for
(
i
=
0
;
i
<
n
;
i
++
)
{
for
(
i
=
0
;
i
<
n
;
i
++
)
{
if
(
git_commit_parent
(
&
commit2
,
commit1
,
0
)
<
0
)
{
if
(
git_commit_parent
(
&
commit2
,
commit1
,
0
)
<
0
)
{
return
GIT_ERROR
;
return
GIT_ERROR
;
}
}
if
(
commit1
!=
(
git_commit
*
)
obj
)
{
if
(
commit1
!=
(
git_commit
*
)
obj
)
{
git_commit_free
(
commit1
);
git_commit_free
(
commit1
);
}
}
commit1
=
commit2
;
commit1
=
commit2
;
}
}
*
out
=
(
git_object
*
)
commit1
;
*
out
=
(
git_object
*
)
commit1
;
return
0
;
return
0
;
}
}
static
int
oid_for_tree_path
(
git_oid
*
out
,
git_tree
*
tree
,
git_repository
*
repo
,
const
char
*
path
)
static
int
oid_for_tree_path
(
git_oid
*
out
,
git_tree
*
tree
,
git_repository
*
repo
,
const
char
*
path
)
{
{
char
*
str
=
git__strdup
(
path
);
char
*
str
,
*
tok
;
char
*
tok
;
void
*
alloc
;
void
*
alloc
=
str
;
git_tree
*
tree2
=
tree
;
git_tree
*
tree2
=
tree
;
const
git_tree_entry
*
entry
=
NULL
;
const
git_tree_entry
*
entry
=
NULL
;
git_otype
type
;
while
((
tok
=
git__strtok
(
&
str
,
"/
\\
"
))
!=
NULL
)
{
if
(
*
path
==
'\0'
)
{
entry
=
git_tree_entry_byname
(
tree2
,
tok
);
git_oid_cpy
(
out
,
git_object_id
((
git_object
*
)
tree
));
if
(
tree2
!=
tree
)
git_tree_free
(
tree2
);
return
0
;
if
(
git_tree_entry__is_tree
(
entry
))
{
}
if
(
git_tree_lookup
(
&
tree2
,
repo
,
&
entry
->
oid
)
<
0
)
{
git__free
(
alloc
);
alloc
=
str
=
git__strdup
(
path
);
return
GIT_ERROR
;
}
while
((
tok
=
git__strtok
(
&
str
,
"/
\\
"
))
!=
NULL
)
{
}
entry
=
git_tree_entry_byname
(
tree2
,
tok
);
}
if
(
tree2
!=
tree
)
git_tree_free
(
tree2
);
if
(
!
entry
)
{
if
(
entry
==
NULL
)
giterr_set
(
GITERR_INVALID
,
"Invalid tree path '%s'"
,
path
);
break
;
git__free
(
alloc
);
return
GIT_ERROR
;
type
=
git_tree_entry_type
(
entry
);
}
switch
(
type
)
{
git_oid_cpy
(
out
,
git_tree_entry_id
(
entry
));
case
GIT_OBJ_TREE
:
git__free
(
alloc
);
if
(
*
str
==
'\0'
)
return
0
;
break
;
if
(
git_tree_lookup
(
&
tree2
,
repo
,
&
entry
->
oid
)
<
0
)
{
git__free
(
alloc
);
return
GIT_ERROR
;
}
break
;
case
GIT_OBJ_BLOB
:
if
(
*
str
!=
'\0'
)
{
entry
=
NULL
;
goto
out
;
}
break
;
default:
/* TODO: support submodules? */
giterr_set
(
GITERR_INVALID
,
"Unimplemented"
);
git__free
(
alloc
);
return
GIT_ERROR
;
}
}
out:
if
(
!
entry
)
{
giterr_set
(
GITERR_INVALID
,
"Invalid tree path '%s'"
,
path
);
git__free
(
alloc
);
return
GIT_ENOTFOUND
;
}
git_oid_cpy
(
out
,
git_tree_entry_id
(
entry
));
git__free
(
alloc
);
return
0
;
}
}
static
int
handle_colon_syntax
(
git_object
**
out
,
static
int
handle_colon_syntax
(
git_object
**
out
,
git_repository
*
repo
,
git_repository
*
repo
,
git_object
*
obj
,
git_object
*
obj
,
const
char
*
path
)
const
char
*
path
)
{
{
git_tree
*
tree
;
git_tree
*
tree
;
git_oid
oid
;
git_oid
oid
;
int
error
;
int
error
;
/* Dereference until we reach a tree. */
/* Dereference until we reach a tree. */
if
(
dereference_to_type
(
&
obj
,
obj
,
GIT_OBJ_TREE
)
<
0
)
{
if
(
dereference_to_type
(
&
obj
,
obj
,
GIT_OBJ_TREE
)
<
0
)
{
return
GIT_ERROR
;
return
GIT_ERROR
;
}
}
tree
=
(
git_tree
*
)
obj
;
tree
=
(
git_tree
*
)
obj
;
/* Find the blob
at the given path. */
/* Find the blob or tree
at the given path. */
error
=
oid_for_tree_path
(
&
oid
,
tree
,
repo
,
path
);
error
=
oid_for_tree_path
(
&
oid
,
tree
,
repo
,
path
);
git_tree_free
(
tree
);
git_tree_free
(
tree
);
if
(
error
<
0
)
if
(
error
<
0
)
return
error
;
return
error
;
return
git_object_lookup
(
out
,
repo
,
&
oid
,
GIT_OBJ_ANY
);
return
git_object_lookup
(
out
,
repo
,
&
oid
,
GIT_OBJ_ANY
);
}
}
static
int
revparse_global_grep
(
git_object
**
out
,
git_repository
*
repo
,
const
char
*
pattern
)
static
int
revparse_global_grep
(
git_object
**
out
,
git_repository
*
repo
,
const
char
*
pattern
)
{
{
git_revwalk
*
walk
;
git_revwalk
*
walk
;
int
retcode
=
GIT_ERROR
;
int
retcode
=
GIT_ERROR
;
if
(
!
pattern
[
0
])
{
if
(
!
pattern
[
0
])
{
giterr_set
(
GITERR_REGEX
,
"Empty pattern"
);
giterr_set
(
GITERR_REGEX
,
"Empty pattern"
);
return
GIT_ERROR
;
return
GIT_ERROR
;
}
}
if
(
!
git_revwalk_new
(
&
walk
,
repo
))
{
if
(
!
git_revwalk_new
(
&
walk
,
repo
))
{
regex_t
preg
;
regex_t
preg
;
int
reg_error
;
int
reg_error
;
git_oid
oid
;
git_oid
oid
;
git_revwalk_sorting
(
walk
,
GIT_SORT_TIME
);
git_revwalk_sorting
(
walk
,
GIT_SORT_TIME
);
git_revwalk_push_glob
(
walk
,
"refs/heads/*"
);
git_revwalk_push_glob
(
walk
,
"refs/heads/*"
);
reg_error
=
regcomp
(
&
preg
,
pattern
,
REG_EXTENDED
);
reg_error
=
regcomp
(
&
preg
,
pattern
,
REG_EXTENDED
);
if
(
reg_error
!=
0
)
{
if
(
reg_error
!=
0
)
{
giterr_set_regex
(
&
preg
,
reg_error
);
giterr_set_regex
(
&
preg
,
reg_error
);
}
else
{
}
else
{
git_object
*
walkobj
=
NULL
,
*
resultobj
=
NULL
;
git_object
*
walkobj
=
NULL
,
*
resultobj
=
NULL
;
while
(
!
git_revwalk_next
(
&
oid
,
walk
))
{
while
(
!
git_revwalk_next
(
&
oid
,
walk
))
{
/* Fetch the commit object, and check for matches in the message */
/* Fetch the commit object, and check for matches in the message */
if
(
walkobj
!=
resultobj
)
git_object_free
(
walkobj
);
if
(
walkobj
!=
resultobj
)
git_object_free
(
walkobj
);
if
(
!
git_object_lookup
(
&
walkobj
,
repo
,
&
oid
,
GIT_OBJ_COMMIT
))
{
if
(
!
git_object_lookup
(
&
walkobj
,
repo
,
&
oid
,
GIT_OBJ_COMMIT
))
{
if
(
!
regexec
(
&
preg
,
git_commit_message
((
git_commit
*
)
walkobj
),
0
,
NULL
,
0
))
{
if
(
!
regexec
(
&
preg
,
git_commit_message
((
git_commit
*
)
walkobj
),
0
,
NULL
,
0
))
{
/* Match! */
/* Match! */
resultobj
=
walkobj
;
resultobj
=
walkobj
;
retcode
=
0
;
retcode
=
0
;
break
;
break
;
}
}
}
}
}
}
if
(
!
resultobj
)
{
if
(
!
resultobj
)
{
giterr_set
(
GITERR_REFERENCE
,
"Couldn't find a match for %s"
,
pattern
);
giterr_set
(
GITERR_REFERENCE
,
"Couldn't find a match for %s"
,
pattern
);
git_object_free
(
walkobj
);
retcode
=
GIT_ENOTFOUND
;
}
else
{
git_object_free
(
walkobj
);
*
out
=
resultobj
;
}
else
{
}
*
out
=
resultobj
;
regfree
(
&
preg
);
}
git_revwalk_free
(
walk
);
regfree
(
&
preg
);
}
git_revwalk_free
(
walk
);
}
}
}
return
retcode
;
return
retcode
;
}
}
int
git_revparse_single
(
git_object
**
out
,
git_repository
*
repo
,
const
char
*
spec
)
int
git_revparse_single
(
git_object
**
out
,
git_repository
*
repo
,
const
char
*
spec
)
{
{
revparse_state
current_state
=
REVPARSE_STATE_INIT
,
next_state
=
REVPARSE_STATE_INIT
;
revparse_state
current_state
=
REVPARSE_STATE_INIT
,
next_state
=
REVPARSE_STATE_INIT
;
const
char
*
spec_cur
=
spec
;
const
char
*
spec_cur
=
spec
;
git_object
*
cur_obj
=
NULL
,
*
next_obj
=
NULL
;
git_object
*
cur_obj
=
NULL
,
*
next_obj
=
NULL
;
git_buf
specbuffer
=
GIT_BUF_INIT
,
stepbuffer
=
GIT_BUF_INIT
;
git_buf
specbuffer
=
GIT_BUF_INIT
,
stepbuffer
=
GIT_BUF_INIT
;
int
retcode
=
0
;
int
retcode
=
0
;
assert
(
out
&&
repo
&&
spec
);
assert
(
out
&&
repo
&&
spec
);
if
(
spec
[
0
]
==
':'
)
{
if
(
spec
[
0
]
==
':'
)
{
if
(
spec
[
1
]
==
'/'
)
{
if
(
spec
[
1
]
==
'/'
)
{
return
revparse_global_grep
(
out
,
repo
,
spec
+
2
);
return
revparse_global_grep
(
out
,
repo
,
spec
+
2
);
}
}
/* TODO: support merge-stage path lookup (":2:Makefile"). */
/* TODO: support merge-stage path lookup (":2:Makefile"). */
giterr_set
(
GITERR_INVALID
,
"Unimplemented"
);
giterr_set
(
GITERR_INVALID
,
"Unimplemented"
);
return
GIT_ERROR
;
return
GIT_ERROR
;
}
}
while
(
current_state
!=
REVPARSE_STATE_DONE
)
{
while
(
current_state
!=
REVPARSE_STATE_DONE
)
{
switch
(
current_state
)
{
switch
(
current_state
)
{
case
REVPARSE_STATE_INIT
:
case
REVPARSE_STATE_INIT
:
if
(
!*
spec_cur
)
{
if
(
!*
spec_cur
)
{
/* No operators, just a name. Find it and return. */
/* No operators, just a name. Find it and return. */
retcode
=
revparse_lookup_object
(
out
,
repo
,
spec
);
retcode
=
revparse_lookup_object
(
out
,
repo
,
spec
);
next_state
=
REVPARSE_STATE_DONE
;
next_state
=
REVPARSE_STATE_DONE
;
}
else
if
(
*
spec_cur
==
'@'
)
{
}
else
if
(
*
spec_cur
==
'@'
)
{
/* '@' syntax doesn't allow chaining */
/* '@' syntax doesn't allow chaining */
git_buf_puts
(
&
stepbuffer
,
spec_cur
);
git_buf_puts
(
&
stepbuffer
,
spec_cur
);
retcode
=
walk_ref_history
(
out
,
repo
,
git_buf_cstr
(
&
specbuffer
),
git_buf_cstr
(
&
stepbuffer
));
retcode
=
walk_ref_history
(
out
,
repo
,
git_buf_cstr
(
&
specbuffer
),
git_buf_cstr
(
&
stepbuffer
));
next_state
=
REVPARSE_STATE_DONE
;
next_state
=
REVPARSE_STATE_DONE
;
}
else
if
(
*
spec_cur
==
'^'
)
{
}
else
if
(
*
spec_cur
==
'^'
)
{
next_state
=
REVPARSE_STATE_CARET
;
next_state
=
REVPARSE_STATE_CARET
;
}
else
if
(
*
spec_cur
==
'~'
)
{
}
else
if
(
*
spec_cur
==
'~'
)
{
next_state
=
REVPARSE_STATE_LINEAR
;
next_state
=
REVPARSE_STATE_LINEAR
;
}
else
if
(
*
spec_cur
==
':'
)
{
}
else
if
(
*
spec_cur
==
':'
)
{
next_state
=
REVPARSE_STATE_COLON
;
next_state
=
REVPARSE_STATE_COLON
;
}
else
{
}
else
{
git_buf_putc
(
&
specbuffer
,
*
spec_cur
);
git_buf_putc
(
&
specbuffer
,
*
spec_cur
);
}
}
spec_cur
++
;
spec_cur
++
;
if
(
current_state
!=
next_state
&&
next_state
!=
REVPARSE_STATE_DONE
)
{
if
(
current_state
!=
next_state
&&
next_state
!=
REVPARSE_STATE_DONE
)
{
/* Leaving INIT state, find the object specified, in case that state needs it */
/* Leaving INIT state, find the object specified, in case that state needs it */
if
(
revparse_lookup_object
(
&
next_obj
,
repo
,
git_buf_cstr
(
&
specbuffer
))
<
0
)
{
if
(
revparse_lookup_object
(
&
next_obj
,
repo
,
git_buf_cstr
(
&
specbuffer
))
<
0
)
{
retcode
=
GIT_ERROR
;
retcode
=
GIT_ERROR
;
next_state
=
REVPARSE_STATE_DONE
;
next_state
=
REVPARSE_STATE_DONE
;
}
}
}
}
break
;
break
;
case
REVPARSE_STATE_CARET
:
case
REVPARSE_STATE_CARET
:
/* Gather characters until NULL, '~', or '^' */
/* Gather characters until NULL, '~', or '^' */
if
(
!*
spec_cur
)
{
if
(
!*
spec_cur
)
{
retcode
=
handle_caret_syntax
(
out
,
repo
,
cur_obj
,
git_buf_cstr
(
&
stepbuffer
));
retcode
=
handle_caret_syntax
(
out
,
repo
,
cur_obj
,
git_buf_cstr
(
&
stepbuffer
));
next_state
=
REVPARSE_STATE_DONE
;
next_state
=
REVPARSE_STATE_DONE
;
}
else
if
(
*
spec_cur
==
'~'
)
{
}
else
if
(
*
spec_cur
==
'~'
)
{
retcode
=
handle_caret_syntax
(
&
next_obj
,
repo
,
cur_obj
,
git_buf_cstr
(
&
stepbuffer
));
retcode
=
handle_caret_syntax
(
&
next_obj
,
repo
,
cur_obj
,
git_buf_cstr
(
&
stepbuffer
));
git_buf_clear
(
&
stepbuffer
);
git_buf_clear
(
&
stepbuffer
);
next_state
=
!
retcode
?
REVPARSE_STATE_LINEAR
:
REVPARSE_STATE_DONE
;
next_state
=
!
retcode
?
REVPARSE_STATE_LINEAR
:
REVPARSE_STATE_DONE
;
}
else
if
(
*
spec_cur
==
'^'
)
{
}
else
if
(
*
spec_cur
==
'^'
)
{
retcode
=
handle_caret_syntax
(
&
next_obj
,
repo
,
cur_obj
,
git_buf_cstr
(
&
stepbuffer
));
retcode
=
handle_caret_syntax
(
&
next_obj
,
repo
,
cur_obj
,
git_buf_cstr
(
&
stepbuffer
));
git_buf_clear
(
&
stepbuffer
);
git_buf_clear
(
&
stepbuffer
);
if
(
retcode
<
0
)
{
if
(
retcode
<
0
)
{
next_state
=
REVPARSE_STATE_DONE
;
next_state
=
REVPARSE_STATE_DONE
;
}
}
}
else
{
}
else
if
(
*
spec_cur
==
':'
)
{
git_buf_putc
(
&
stepbuffer
,
*
spec_cur
);
retcode
=
handle_caret_syntax
(
&
next_obj
,
repo
,
cur_obj
,
git_buf_cstr
(
&
stepbuffer
));
}
git_buf_clear
(
&
stepbuffer
);
spec_cur
++
;
next_state
=
!
retcode
?
REVPARSE_STATE_COLON
:
REVPARSE_STATE_DONE
;
break
;
}
else
{
git_buf_putc
(
&
stepbuffer
,
*
spec_cur
);
case
REVPARSE_STATE_LINEAR
:
}
if
(
!*
spec_cur
)
{
spec_cur
++
;
retcode
=
handle_linear_syntax
(
out
,
cur_obj
,
git_buf_cstr
(
&
stepbuffer
));
break
;
next_state
=
REVPARSE_STATE_DONE
;
}
else
if
(
*
spec_cur
==
'~'
)
{
case
REVPARSE_STATE_LINEAR
:
retcode
=
handle_linear_syntax
(
&
next_obj
,
cur_obj
,
git_buf_cstr
(
&
stepbuffer
));
if
(
!*
spec_cur
)
{
git_buf_clear
(
&
stepbuffer
);
retcode
=
handle_linear_syntax
(
out
,
cur_obj
,
git_buf_cstr
(
&
stepbuffer
));
if
(
retcode
<
0
)
{
next_state
=
REVPARSE_STATE_DONE
;
next_state
=
REVPARSE_STATE_DONE
;
}
else
if
(
*
spec_cur
==
'~'
)
{
}
retcode
=
handle_linear_syntax
(
&
next_obj
,
cur_obj
,
git_buf_cstr
(
&
stepbuffer
));
}
else
if
(
*
spec_cur
==
'^'
)
{
git_buf_clear
(
&
stepbuffer
);
retcode
=
handle_linear_syntax
(
&
next_obj
,
cur_obj
,
git_buf_cstr
(
&
stepbuffer
));
if
(
retcode
<
0
)
{
git_buf_clear
(
&
stepbuffer
);
next_state
=
REVPARSE_STATE_DONE
;
next_state
=
!
retcode
?
REVPARSE_STATE_CARET
:
REVPARSE_STATE_DONE
;
}
}
else
{
}
else
if
(
*
spec_cur
==
'^'
)
{
git_buf_putc
(
&
stepbuffer
,
*
spec_cur
);
retcode
=
handle_linear_syntax
(
&
next_obj
,
cur_obj
,
git_buf_cstr
(
&
stepbuffer
));
}
git_buf_clear
(
&
stepbuffer
);
spec_cur
++
;
next_state
=
!
retcode
?
REVPARSE_STATE_CARET
:
REVPARSE_STATE_DONE
;
break
;
}
else
{
git_buf_putc
(
&
stepbuffer
,
*
spec_cur
);
case
REVPARSE_STATE_COLON
:
}
if
(
*
spec_cur
)
{
spec_cur
++
;
git_buf_putc
(
&
stepbuffer
,
*
spec_cur
);
break
;
}
else
{
retcode
=
handle_colon_syntax
(
out
,
repo
,
cur_obj
,
git_buf_cstr
(
&
stepbuffer
));
case
REVPARSE_STATE_COLON
:
next_state
=
REVPARSE_STATE_DONE
;
if
(
*
spec_cur
)
{
}
git_buf_putc
(
&
stepbuffer
,
*
spec_cur
);
spec_cur
++
;
}
else
{
break
;
retcode
=
handle_colon_syntax
(
out
,
repo
,
cur_obj
,
git_buf_cstr
(
&
stepbuffer
));
next_state
=
REVPARSE_STATE_DONE
;
case
REVPARSE_STATE_DONE
:
}
if
(
cur_obj
&&
*
out
!=
cur_obj
)
git_object_free
(
cur_obj
);
spec_cur
++
;
if
(
next_obj
&&
*
out
!=
next_obj
)
git_object_free
(
next_obj
);
break
;
break
;
}
case
REVPARSE_STATE_DONE
:
if
(
cur_obj
&&
*
out
!=
cur_obj
)
git_object_free
(
cur_obj
);
current_state
=
next_state
;
if
(
next_obj
&&
*
out
!=
next_obj
)
git_object_free
(
next_obj
);
if
(
cur_obj
!=
next_obj
)
{
break
;
if
(
cur_obj
)
git_object_free
(
cur_obj
);
}
cur_obj
=
next_obj
;
}
current_state
=
next_state
;
}
if
(
cur_obj
!=
next_obj
)
{
if
(
cur_obj
)
git_object_free
(
cur_obj
);
if
(
*
out
!=
cur_obj
)
git_object_free
(
cur_obj
);
cur_obj
=
next_obj
;
if
(
*
out
!=
next_obj
&&
next_obj
!=
cur_obj
)
git_object_free
(
next_obj
);
}
}
git_buf_free
(
&
specbuffer
);
git_buf_free
(
&
stepbuffer
);
if
(
*
out
!=
cur_obj
)
git_object_free
(
cur_obj
);
return
retcode
;
if
(
*
out
!=
next_obj
&&
next_obj
!=
cur_obj
)
git_object_free
(
next_obj
);
git_buf_free
(
&
specbuffer
);
git_buf_free
(
&
stepbuffer
);
return
retcode
;
}
}
tests-clar/refs/revparse.c
View file @
cbc02c10
...
@@ -11,168 +11,181 @@ static char g_orig_tz[16] = {0};
...
@@ -11,168 +11,181 @@ static char g_orig_tz[16] = {0};
/* Helpers */
/* Helpers */
static
void
test_object
(
const
char
*
spec
,
const
char
*
expected_oid
)
static
void
test_object
(
const
char
*
spec
,
const
char
*
expected_oid
)
{
{
char
objstr
[
64
]
=
{
0
};
char
objstr
[
64
]
=
{
0
};
cl_git_pass
(
git_revparse_single
(
&
g_obj
,
g_repo
,
spec
));
cl_git_pass
(
git_revparse_single
(
&
g_obj
,
g_repo
,
spec
));
git_oid_fmt
(
objstr
,
git_object_id
(
g_obj
));
git_oid_fmt
(
objstr
,
git_object_id
(
g_obj
));
cl_assert_equal_s
(
objstr
,
expected_oid
);
cl_assert_equal_s
(
objstr
,
expected_oid
);
git_object_free
(
g_obj
);
git_object_free
(
g_obj
);
g_obj
=
NULL
;
g_obj
=
NULL
;
}
}
void
test_refs_revparse__initialize
(
void
)
void
test_refs_revparse__initialize
(
void
)
{
{
char
*
tz
=
cl_getenv
(
"TZ"
);
char
*
tz
=
cl_getenv
(
"TZ"
);
if
(
tz
)
if
(
tz
)
strcpy
(
g_orig_tz
,
tz
);
strcpy
(
g_orig_tz
,
tz
);
cl_setenv
(
"TZ"
,
"UTC"
);
cl_setenv
(
"TZ"
,
"UTC"
);
g_repo
=
cl_git_sandbox_init
(
"testrepo.git"
);
g_repo
=
cl_git_sandbox_init
(
"testrepo.git"
);
}
}
void
test_refs_revparse__cleanup
(
void
)
void
test_refs_revparse__cleanup
(
void
)
{
{
cl_git_sandbox_cleanup
();
cl_git_sandbox_cleanup
();
g_obj
=
NULL
;
g_obj
=
NULL
;
cl_setenv
(
"TZ"
,
g_orig_tz
);
cl_setenv
(
"TZ"
,
g_orig_tz
);
}
}
void
test_refs_revparse__nonexistant_object
(
void
)
void
test_refs_revparse__nonexistant_object
(
void
)
{
{
cl_git_fail
(
git_revparse_single
(
&
g_obj
,
g_repo
,
"this doesn't exist"
));
cl_git_fail
(
git_revparse_single
(
&
g_obj
,
g_repo
,
"this doesn't exist"
));
cl_git_fail
(
git_revparse_single
(
&
g_obj
,
g_repo
,
"this doesn't exist^1"
));
cl_git_fail
(
git_revparse_single
(
&
g_obj
,
g_repo
,
"this doesn't exist^1"
));
cl_git_fail
(
git_revparse_single
(
&
g_obj
,
g_repo
,
"this doesn't exist~2"
));
cl_git_fail
(
git_revparse_single
(
&
g_obj
,
g_repo
,
"this doesn't exist~2"
));
}
}
void
test_refs_revparse__shas
(
void
)
void
test_refs_revparse__shas
(
void
)
{
{
test_object
(
"c47800c7266a2be04c571c04d5a6614691ea99bd"
,
"c47800c7266a2be04c571c04d5a6614691ea99bd"
);
test_object
(
"c47800c7266a2be04c571c04d5a6614691ea99bd"
,
"c47800c7266a2be04c571c04d5a6614691ea99bd"
);
test_object
(
"c47800c"
,
"c47800c7266a2be04c571c04d5a6614691ea99bd"
);
test_object
(
"c47800c"
,
"c47800c7266a2be04c571c04d5a6614691ea99bd"
);
}
}
void
test_refs_revparse__head
(
void
)
void
test_refs_revparse__head
(
void
)
{
{
test_object
(
"HEAD"
,
"a65fedf39aefe402d3bb6e24df4d4f5fe4547750"
);
test_object
(
"HEAD"
,
"a65fedf39aefe402d3bb6e24df4d4f5fe4547750"
);
}
}
void
test_refs_revparse__full_refs
(
void
)
void
test_refs_revparse__full_refs
(
void
)
{
{
test_object
(
"refs/heads/master"
,
"a65fedf39aefe402d3bb6e24df4d4f5fe4547750"
);
test_object
(
"refs/heads/master"
,
"a65fedf39aefe402d3bb6e24df4d4f5fe4547750"
);
test_object
(
"refs/heads/test"
,
"e90810b8df3e80c413d903f631643c716887138d"
);
test_object
(
"refs/heads/test"
,
"e90810b8df3e80c413d903f631643c716887138d"
);
test_object
(
"refs/tags/test"
,
"b25fa35b38051e4ae45d4222e795f9df2e43f1d1"
);
test_object
(
"refs/tags/test"
,
"b25fa35b38051e4ae45d4222e795f9df2e43f1d1"
);
}
}
void
test_refs_revparse__partial_refs
(
void
)
void
test_refs_revparse__partial_refs
(
void
)
{
{
test_object
(
"point_to_blob"
,
"1385f264afb75a56a5bec74243be9b367ba4ca08"
);
test_object
(
"point_to_blob"
,
"1385f264afb75a56a5bec74243be9b367ba4ca08"
);
test_object
(
"packed-test"
,
"4a202b346bb0fb0db7eff3cffeb3c70babbd2045"
);
test_object
(
"packed-test"
,
"4a202b346bb0fb0db7eff3cffeb3c70babbd2045"
);
test_object
(
"br2"
,
"a4a7dce85cf63874e984719f4fdd239f5145052f"
);
test_object
(
"br2"
,
"a4a7dce85cf63874e984719f4fdd239f5145052f"
);
}
}
void
test_refs_revparse__describe_output
(
void
)
void
test_refs_revparse__describe_output
(
void
)
{
{
test_object
(
"blah-7-gc47800c"
,
"c47800c7266a2be04c571c04d5a6614691ea99bd"
);
test_object
(
"blah-7-gc47800c"
,
"c47800c7266a2be04c571c04d5a6614691ea99bd"
);
test_object
(
"not-good"
,
"a65fedf39aefe402d3bb6e24df4d4f5fe4547750"
);
test_object
(
"not-good"
,
"a65fedf39aefe402d3bb6e24df4d4f5fe4547750"
);
}
}
void
test_refs_revparse__nth_parent
(
void
)
void
test_refs_revparse__nth_parent
(
void
)
{
{
test_object
(
"be3563a^1"
,
"9fd738e8f7967c078dceed8190330fc8648ee56a"
);
test_object
(
"be3563a^1"
,
"9fd738e8f7967c078dceed8190330fc8648ee56a"
);
test_object
(
"be3563a^"
,
"9fd738e8f7967c078dceed8190330fc8648ee56a"
);
test_object
(
"be3563a^"
,
"9fd738e8f7967c078dceed8190330fc8648ee56a"
);
test_object
(
"be3563a^2"
,
"c47800c7266a2be04c571c04d5a6614691ea99bd"
);
test_object
(
"be3563a^2"
,
"c47800c7266a2be04c571c04d5a6614691ea99bd"
);
test_object
(
"be3563a^1^1"
,
"4a202b346bb0fb0db7eff3cffeb3c70babbd2045"
);
test_object
(
"be3563a^1^1"
,
"4a202b346bb0fb0db7eff3cffeb3c70babbd2045"
);
test_object
(
"be3563a^2^1"
,
"5b5b025afb0b4c913b4c338a42934a3863bf3644"
);
test_object
(
"be3563a^2^1"
,
"5b5b025afb0b4c913b4c338a42934a3863bf3644"
);
test_object
(
"be3563a^0"
,
"be3563ae3f795b2b4353bcce3a527ad0a4f7f644"
);
test_object
(
"be3563a^0"
,
"be3563ae3f795b2b4353bcce3a527ad0a4f7f644"
);
cl_assert_equal_i
(
GIT_ENOTFOUND
,
git_revparse_single
(
&
g_obj
,
g_repo
,
"be3563a^42"
));
}
}
void
test_refs_revparse__not_tag
(
void
)
void
test_refs_revparse__not_tag
(
void
)
{
{
test_object
(
"point_to_blob^{}"
,
"1385f264afb75a56a5bec74243be9b367ba4ca08"
);
test_object
(
"point_to_blob^{}"
,
"1385f264afb75a56a5bec74243be9b367ba4ca08"
);
test_object
(
"wrapped_tag^{}"
,
"a65fedf39aefe402d3bb6e24df4d4f5fe4547750"
);
test_object
(
"wrapped_tag^{}"
,
"a65fedf39aefe402d3bb6e24df4d4f5fe4547750"
);
}
}
void
test_refs_revparse__to_type
(
void
)
void
test_refs_revparse__to_type
(
void
)
{
{
test_object
(
"wrapped_tag^{commit}"
,
"a65fedf39aefe402d3bb6e24df4d4f5fe4547750"
);
test_object
(
"wrapped_tag^{commit}"
,
"a65fedf39aefe402d3bb6e24df4d4f5fe4547750"
);
test_object
(
"wrapped_tag^{tree}"
,
"944c0f6e4dfa41595e6eb3ceecdb14f50fe18162"
);
test_object
(
"wrapped_tag^{tree}"
,
"944c0f6e4dfa41595e6eb3ceecdb14f50fe18162"
);
test_object
(
"point_to_blob^{blob}"
,
"1385f264afb75a56a5bec74243be9b367ba4ca08"
);
test_object
(
"point_to_blob^{blob}"
,
"1385f264afb75a56a5bec74243be9b367ba4ca08"
);
cl_git_fail
(
git_revparse_single
(
&
g_obj
,
g_repo
,
"wrapped_tag^{blob}"
));
cl_git_fail
(
git_revparse_single
(
&
g_obj
,
g_repo
,
"wrapped_tag^{blob}"
));
}
}
void
test_refs_revparse__linear_history
(
void
)
void
test_refs_revparse__linear_history
(
void
)
{
{
cl_git_fail
(
git_revparse_single
(
&
g_obj
,
g_repo
,
"foo~bar"
));
cl_git_fail
(
git_revparse_single
(
&
g_obj
,
g_repo
,
"foo~bar"
));
cl_git_fail
(
git_revparse_single
(
&
g_obj
,
g_repo
,
"master~bar"
));
cl_git_fail
(
git_revparse_single
(
&
g_obj
,
g_repo
,
"master~bar"
));
test_object
(
"master~0"
,
"a65fedf39aefe402d3bb6e24df4d4f5fe4547750"
);
test_object
(
"master~0"
,
"a65fedf39aefe402d3bb6e24df4d4f5fe4547750"
);
test_object
(
"master~1"
,
"be3563ae3f795b2b4353bcce3a527ad0a4f7f644"
);
test_object
(
"master~1"
,
"be3563ae3f795b2b4353bcce3a527ad0a4f7f644"
);
test_object
(
"master~2"
,
"9fd738e8f7967c078dceed8190330fc8648ee56a"
);
test_object
(
"master~2"
,
"9fd738e8f7967c078dceed8190330fc8648ee56a"
);
test_object
(
"master~1~1"
,
"9fd738e8f7967c078dceed8190330fc8648ee56a"
);
test_object
(
"master~1~1"
,
"9fd738e8f7967c078dceed8190330fc8648ee56a"
);
}
}
void
test_refs_revparse__chaining
(
void
)
void
test_refs_revparse__chaining
(
void
)
{
{
test_object
(
"master~1^1"
,
"9fd738e8f7967c078dceed8190330fc8648ee56a"
);
test_object
(
"master~1^1"
,
"9fd738e8f7967c078dceed8190330fc8648ee56a"
);
test_object
(
"master~1^2"
,
"c47800c7266a2be04c571c04d5a6614691ea99bd"
);
test_object
(
"master~1^2"
,
"c47800c7266a2be04c571c04d5a6614691ea99bd"
);
test_object
(
"master^1^2~1"
,
"5b5b025afb0b4c913b4c338a42934a3863bf3644"
);
test_object
(
"master^1^2~1"
,
"5b5b025afb0b4c913b4c338a42934a3863bf3644"
);
test_object
(
"master^1^1^1^1^1"
,
"8496071c1b46c854b31185ea97743be6a8774479"
);
test_object
(
"master^1^1^1^1^1"
,
"8496071c1b46c854b31185ea97743be6a8774479"
);
}
}
void
test_refs_revparse__reflog
(
void
)
void
test_refs_revparse__reflog
(
void
)
{
{
cl_git_fail
(
git_revparse_single
(
&
g_obj
,
g_repo
,
"@{-xyz}"
));
cl_git_fail
(
git_revparse_single
(
&
g_obj
,
g_repo
,
"@{-xyz}"
));
cl_git_fail
(
git_revparse_single
(
&
g_obj
,
g_repo
,
"@{-0}"
));
cl_git_fail
(
git_revparse_single
(
&
g_obj
,
g_repo
,
"@{-0}"
));
cl_git_fail
(
git_revparse_single
(
&
g_obj
,
g_repo
,
"@{1000}"
));
cl_git_fail
(
git_revparse_single
(
&
g_obj
,
g_repo
,
"@{1000}"
));
test_object
(
"@{-2}"
,
"a65fedf39aefe402d3bb6e24df4d4f5fe4547750"
);
test_object
(
"@{-2}"
,
"a65fedf39aefe402d3bb6e24df4d4f5fe4547750"
);
test_object
(
"@{-1}"
,
"a4a7dce85cf63874e984719f4fdd239f5145052f"
);
test_object
(
"@{-1}"
,
"a4a7dce85cf63874e984719f4fdd239f5145052f"
);
test_object
(
"master@{0}"
,
"a65fedf39aefe402d3bb6e24df4d4f5fe4547750"
);
test_object
(
"master@{0}"
,
"a65fedf39aefe402d3bb6e24df4d4f5fe4547750"
);
test_object
(
"master@{1}"
,
"be3563ae3f795b2b4353bcce3a527ad0a4f7f644"
);
test_object
(
"master@{1}"
,
"be3563ae3f795b2b4353bcce3a527ad0a4f7f644"
);
test_object
(
"@{0}"
,
"a65fedf39aefe402d3bb6e24df4d4f5fe4547750"
);
test_object
(
"@{0}"
,
"a65fedf39aefe402d3bb6e24df4d4f5fe4547750"
);
test_object
(
"@{1}"
,
"be3563ae3f795b2b4353bcce3a527ad0a4f7f644"
);
test_object
(
"@{1}"
,
"be3563ae3f795b2b4353bcce3a527ad0a4f7f644"
);
test_object
(
"master@{upstream}"
,
"be3563ae3f795b2b4353bcce3a527ad0a4f7f644"
);
test_object
(
"master@{upstream}"
,
"be3563ae3f795b2b4353bcce3a527ad0a4f7f644"
);
test_object
(
"master@{u}"
,
"be3563ae3f795b2b4353bcce3a527ad0a4f7f644"
);
test_object
(
"master@{u}"
,
"be3563ae3f795b2b4353bcce3a527ad0a4f7f644"
);
}
}
void
test_refs_revparse__revwalk
(
void
)
void
test_refs_revparse__revwalk
(
void
)
{
{
cl_git_fail
(
git_revparse_single
(
&
g_obj
,
g_repo
,
"master^{/not found in any commit}"
));
cl_git_fail
(
git_revparse_single
(
&
g_obj
,
g_repo
,
"master^{/not found in any commit}"
));
cl_git_fail
(
git_revparse_single
(
&
g_obj
,
g_repo
,
"master^{/merge}"
));
cl_git_fail
(
git_revparse_single
(
&
g_obj
,
g_repo
,
"master^{/merge}"
));
cl_git_fail
(
git_revparse_single
(
&
g_obj
,
g_repo
,
"master^{/((}"
));
cl_git_fail
(
git_revparse_single
(
&
g_obj
,
g_repo
,
"master^{/((}"
));
test_object
(
"master^{/anoth}"
,
"5b5b025afb0b4c913b4c338a42934a3863bf3644"
);
test_object
(
"master^{/anoth}"
,
"5b5b025afb0b4c913b4c338a42934a3863bf3644"
);
test_object
(
"master^{/Merge}"
,
"be3563ae3f795b2b4353bcce3a527ad0a4f7f644"
);
test_object
(
"master^{/Merge}"
,
"be3563ae3f795b2b4353bcce3a527ad0a4f7f644"
);
test_object
(
"br2^{/Merge}"
,
"a4a7dce85cf63874e984719f4fdd239f5145052f"
);
test_object
(
"br2^{/Merge}"
,
"a4a7dce85cf63874e984719f4fdd239f5145052f"
);
test_object
(
"master^{/fo.rth}"
,
"9fd738e8f7967c078dceed8190330fc8648ee56a"
);
test_object
(
"master^{/fo.rth}"
,
"9fd738e8f7967c078dceed8190330fc8648ee56a"
);
}
}
void
test_refs_revparse__date
(
void
)
void
test_refs_revparse__date
(
void
)
{
{
test_object
(
"HEAD@{10 years ago}"
,
"be3563ae3f795b2b4353bcce3a527ad0a4f7f644"
);
test_object
(
"HEAD@{10 years ago}"
,
"be3563ae3f795b2b4353bcce3a527ad0a4f7f644"
);
test_object
(
"HEAD@{1 second}"
,
"a65fedf39aefe402d3bb6e24df4d4f5fe4547750"
);
test_object
(
"HEAD@{1 second}"
,
"a65fedf39aefe402d3bb6e24df4d4f5fe4547750"
);
test_object
(
"master@{2012-4-30 10:23:20 -0800}"
,
"be3563ae3f795b2b4353bcce3a527ad0a4f7f644"
);
test_object
(
"master@{2012-4-30 10:23:20 -0800}"
,
"be3563ae3f795b2b4353bcce3a527ad0a4f7f644"
);
test_object
(
"master@{2012-4-30 18:24 -0800}"
,
"a65fedf39aefe402d3bb6e24df4d4f5fe4547750"
);
test_object
(
"master@{2012-4-30 18:24 -0800}"
,
"a65fedf39aefe402d3bb6e24df4d4f5fe4547750"
);
test_object
(
"master@{2012-4-30 23:24 -0300}"
,
"a65fedf39aefe402d3bb6e24df4d4f5fe4547750"
);
test_object
(
"master@{2012-4-30 23:24 -0300}"
,
"a65fedf39aefe402d3bb6e24df4d4f5fe4547750"
);
/* Core git gives a65fedf, because they don't take time zones into account. */
/* Core git gives a65fedf, because they don't take time zones into account. */
test_object
(
"master@{1335806640}"
,
"be3563ae3f795b2b4353bcce3a527ad0a4f7f644"
);
test_object
(
"master@{1335806640}"
,
"be3563ae3f795b2b4353bcce3a527ad0a4f7f644"
);
}
}
void
test_refs_revparse__colon
(
void
)
void
test_refs_revparse__colon
(
void
)
{
{
cl_git_fail
(
git_revparse_single
(
&
g_obj
,
g_repo
,
":/"
));
cl_git_fail
(
git_revparse_single
(
&
g_obj
,
g_repo
,
":/"
));
cl_git_fail
(
git_revparse_single
(
&
g_obj
,
g_repo
,
":/not found in any commit"
));
cl_git_fail
(
git_revparse_single
(
&
g_obj
,
g_repo
,
":2:README"
));
cl_git_fail
(
git_revparse_single
(
&
g_obj
,
g_repo
,
":2:README"
));
cl_git_fail
(
git_revparse_single
(
&
g_obj
,
g_repo
,
"master:"
));
cl_assert_equal_i
(
GIT_ENOTFOUND
,
git_revparse_single
(
&
g_obj
,
g_repo
,
":/not found in any commit"
));
cl_assert_equal_i
(
GIT_ENOTFOUND
,
git_revparse_single
(
&
g_obj
,
g_repo
,
"subtrees:ab/42.txt"
));
test_object
(
"subtrees:ab/4.txt"
,
"d6c93164c249c8000205dd4ec5cbca1b516d487f"
);
cl_assert_equal_i
(
GIT_ENOTFOUND
,
git_revparse_single
(
&
g_obj
,
g_repo
,
"subtrees:ab/4.txt/nope"
));
test_object
(
"subtrees:ab/de/fgh/1.txt"
,
"1f67fc4386b2d171e0d21be1c447e12660561f9b"
);
cl_assert_equal_i
(
GIT_ENOTFOUND
,
git_revparse_single
(
&
g_obj
,
g_repo
,
"subtrees:nope"
));
test_object
(
"master:README"
,
"a8233120f6ad708f843d861ce2b7228ec4e3dec6"
);
cl_assert_equal_i
(
GIT_ENOTFOUND
,
git_revparse_single
(
&
g_obj
,
g_repo
,
"test/master^1:branch_file.txt"
));
test_object
(
"master:new.txt"
,
"a71586c1dfe8a71c6cbf6c129f404c5642ff31bd"
);
test_object
(
":/Merge"
,
"a4a7dce85cf63874e984719f4fdd239f5145052f"
);
/* Trees */
test_object
(
":/one"
,
"c47800c7266a2be04c571c04d5a6614691ea99bd"
);
test_object
(
"master:"
,
"944c0f6e4dfa41595e6eb3ceecdb14f50fe18162"
);
test_object
(
":/packed commit t"
,
"41bc8c69075bbdb46c5c6f0566cc8cc5b46e8bd9"
);
test_object
(
"subtrees:"
,
"ae90f12eea699729ed24555e40b9fd669da12a12"
);
test_object
(
"subtrees:ab"
,
"f1425cef211cc08caa31e7b545ffb232acb098c3"
);
/* Blobs */
test_object
(
"subtrees:ab/4.txt"
,
"d6c93164c249c8000205dd4ec5cbca1b516d487f"
);
test_object
(
"subtrees:ab/de/fgh/1.txt"
,
"1f67fc4386b2d171e0d21be1c447e12660561f9b"
);
test_object
(
"master:README"
,
"a8233120f6ad708f843d861ce2b7228ec4e3dec6"
);
test_object
(
"master:new.txt"
,
"a71586c1dfe8a71c6cbf6c129f404c5642ff31bd"
);
test_object
(
":/Merge"
,
"a4a7dce85cf63874e984719f4fdd239f5145052f"
);
test_object
(
":/one"
,
"c47800c7266a2be04c571c04d5a6614691ea99bd"
);
test_object
(
":/packed commit t"
,
"41bc8c69075bbdb46c5c6f0566cc8cc5b46e8bd9"
);
test_object
(
"test/master^2:branch_file.txt"
,
"45b983be36b73c0788dc9cbcb76cbb80fc7bb057"
);
}
}
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