2013-05-01 23:56:36 +02:00
|
|
|
<?php
|
|
|
|
|
Rename Conduit classes
Summary: Ref T5655. Rename Conduit classes and provide a `getAPIMethodName` method to declare the API method.
Test Plan:
```
> echo '{}' | arc --conduit-uri='http://phabricator.joshuaspence.com' call-conduit user.whoami
Waiting for JSON parameters on stdin...
{"error":null,"errorMessage":null,"response":{"phid":"PHID-USER-lioqffnwn6y475mu5ndb","userName":"josh","realName":"Joshua Spence","image":"http:\/\/phabricator.joshuaspence.com\/res\/1404425321T\/phabricator\/3eb28cd9\/rsrc\/image\/avatar.png","uri":"http:\/\/phabricator.joshuaspence.com\/p\/josh\/","roles":["admin","verified","approved","activated"]}}
```
Reviewers: epriestley, #blessed_reviewers
Reviewed By: epriestley, #blessed_reviewers
Subscribers: epriestley, Korvin, hach-que
Maniphest Tasks: T5655
Differential Revision: https://secure.phabricator.com/D9991
2014-07-25 02:54:15 +02:00
|
|
|
final class DiffusionBranchQueryConduitAPIMethod
|
|
|
|
extends DiffusionQueryConduitAPIMethod {
|
|
|
|
|
|
|
|
public function getAPIMethodName() {
|
|
|
|
return 'diffusion.branchquery';
|
|
|
|
}
|
2013-05-01 23:56:36 +02:00
|
|
|
|
|
|
|
public function getMethodDescription() {
|
2014-01-18 01:11:04 +01:00
|
|
|
return pht('Determine what branches exist for a repository.');
|
2013-05-01 23:56:36 +02:00
|
|
|
}
|
|
|
|
|
2015-04-13 00:59:07 +02:00
|
|
|
protected function defineReturnType() {
|
2014-01-18 01:11:04 +01:00
|
|
|
return 'list<dict>';
|
2013-05-01 23:56:36 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
protected function defineCustomParamTypes() {
|
|
|
|
return array(
|
2015-04-27 12:51:21 +02:00
|
|
|
'closed' => 'optional bool',
|
2013-05-01 23:56:36 +02:00
|
|
|
'limit' => 'optional int',
|
2014-01-18 01:11:04 +01:00
|
|
|
'offset' => 'optional int',
|
|
|
|
'contains' => 'optional string',
|
2013-05-01 23:56:36 +02:00
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
protected function getGitResult(ConduitAPIRequest $request) {
|
|
|
|
$drequest = $this->getDiffusionRequest();
|
|
|
|
$repository = $drequest->getRepository();
|
|
|
|
|
2014-01-18 01:11:04 +01:00
|
|
|
$contains = $request->getValue('contains');
|
|
|
|
if (strlen($contains)) {
|
|
|
|
// NOTE: We can't use DiffusionLowLevelGitRefQuery here because
|
|
|
|
// `git for-each-ref` does not support `--contains`.
|
|
|
|
if ($repository->isWorkingCopyBare()) {
|
|
|
|
list($stdout) = $repository->execxLocalCommand(
|
|
|
|
'branch --verbose --no-abbrev --contains %s --',
|
|
|
|
$contains);
|
|
|
|
$ref_map = DiffusionGitBranch::parseLocalBranchOutput(
|
|
|
|
$stdout);
|
|
|
|
} else {
|
|
|
|
list($stdout) = $repository->execxLocalCommand(
|
|
|
|
'branch -r --verbose --no-abbrev --contains %s --',
|
|
|
|
$contains);
|
|
|
|
$ref_map = DiffusionGitBranch::parseRemoteBranchOutput(
|
|
|
|
$stdout,
|
|
|
|
DiffusionGitBranch::DEFAULT_GIT_REMOTE);
|
|
|
|
}
|
|
|
|
|
|
|
|
$refs = array();
|
|
|
|
foreach ($ref_map as $ref => $commit) {
|
|
|
|
$refs[] = id(new DiffusionRepositoryRef())
|
|
|
|
->setShortName($ref)
|
|
|
|
->setCommitIdentifier($commit);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
$refs = id(new DiffusionLowLevelGitRefQuery())
|
|
|
|
->setRepository($repository)
|
Version clustered, observed repositories in a reasonable way (by largest discovered HEAD)
Summary:
Ref T4292. For hosted, clustered repositories we have a good way to increment the internal version of the repository: every time a user pushes something, we increment the version by 1.
We don't have a great way to do this for observed/remote repositories because when we `git fetch` we might get nothing, or we might get some changes, and we can't easily tell //what// changes we got.
For example, if we see that another node is at "version 97", and we do a fetch and see some changes, we don't know if we're in sync with them (i.e., also at "version 97") or ahead of them (at "version 98").
This implements a simple way to version an observed repository:
- Take the head of every branch/tag.
- Look them up.
- Pick the biggest internal ID number.
This will work //except// when branches are deleted, which could cause the version to go backward if the "biggest commit" is the one that was deleted. This should be OK, since it's rare and the effects are minor and the repository will "self-heal" on the next actual push.
Test Plan:
- Created an observed repository.
- Ran `bin/repository update` and observed a sensible version number appear in the version table.
- Pushed to the remote, did another update, saw a sensible update.
- Did an update with no push, saw no effect on version number.
- Toggled repository to hosted, saw the version reset.
- Simulated read traffic to out-of-sync node, saw it do a remote fetch.
Reviewers: chad
Reviewed By: chad
Maniphest Tasks: T4292
Differential Revision: https://secure.phabricator.com/D15986
2016-05-27 15:21:19 +02:00
|
|
|
->withRefTypes(
|
|
|
|
array(
|
|
|
|
PhabricatorRepositoryRefCursor::TYPE_BRANCH,
|
|
|
|
))
|
2014-01-18 01:11:04 +01:00
|
|
|
->execute();
|
|
|
|
}
|
2013-05-01 23:56:36 +02:00
|
|
|
|
2014-01-18 01:10:56 +01:00
|
|
|
return $this->processBranchRefs($request, $refs);
|
|
|
|
}
|
2013-10-30 21:06:09 +01:00
|
|
|
|
2014-01-18 01:10:56 +01:00
|
|
|
protected function getMercurialResult(ConduitAPIRequest $request) {
|
|
|
|
$drequest = $this->getDiffusionRequest();
|
|
|
|
$repository = $drequest->getRepository();
|
2013-05-01 23:56:36 +02:00
|
|
|
|
Never use "{branches}" in Mercurial
Summary:
Fixes T5304. Mercurial features a "{branches}" template keyword, documented as:
```
branches List of strings. The name of the branch on which the
changeset was committed. Will be empty if the branch name
was default.
```
At some time long in the past, I misinterpreted this to mean "list of branches where the branch head is a descendant of the commit". It is more like "list of zero or one elements, possibly containing the name of the branch the commit was originally made to, if that branch was not 'default'".
In fact, it seems like this is because a //very// long time in the past, Mercurial worked roughly like I expected:
> Ages ago (2005), we had a very different and ultimately unworkable
> approach to named branches that worked vaguely like .hgtags and allowed
> multiple branch names per revision.
http://marc.info/?l=mercurial-devel&m=129883069414855
This appears to be deprecated in modern Mercurial (it's not in the modern web documentation) although I can't find a commit about it so maybe that's just a documentation issue.
In any case, `{branches}` seems to never be useful: `{branch}` provides the same information without the awkward "default-if-empty" case.
Switch from `{branches}` to either `{branch}` (where that's good enough, notably in the hook engine) or `(descendants(%s) and head())`, which is equivalent to `--contains` in Git.
This fixes pushing to branches with spaces in their names, and makes the "Branches" / "Contains" queries moderately more consistent.
Test Plan:
- Pushed to a Mercurial branch with a space in it.
- Viewed list of branches in a Mercurial repository.
- Viewed containing branches of a Mercurial commit in Diffusion.
Reviewers: btrahan
Reviewed By: btrahan
Subscribers: epriestley
Maniphest Tasks: T5304
Differential Revision: https://secure.phabricator.com/D9453
2014-06-20 20:48:31 +02:00
|
|
|
$query = id(new DiffusionLowLevelMercurialBranchesQuery())
|
|
|
|
->setRepository($repository);
|
2013-05-01 23:56:36 +02:00
|
|
|
|
2014-01-18 01:11:04 +01:00
|
|
|
$contains = $request->getValue('contains');
|
|
|
|
if (strlen($contains)) {
|
Never use "{branches}" in Mercurial
Summary:
Fixes T5304. Mercurial features a "{branches}" template keyword, documented as:
```
branches List of strings. The name of the branch on which the
changeset was committed. Will be empty if the branch name
was default.
```
At some time long in the past, I misinterpreted this to mean "list of branches where the branch head is a descendant of the commit". It is more like "list of zero or one elements, possibly containing the name of the branch the commit was originally made to, if that branch was not 'default'".
In fact, it seems like this is because a //very// long time in the past, Mercurial worked roughly like I expected:
> Ages ago (2005), we had a very different and ultimately unworkable
> approach to named branches that worked vaguely like .hgtags and allowed
> multiple branch names per revision.
http://marc.info/?l=mercurial-devel&m=129883069414855
This appears to be deprecated in modern Mercurial (it's not in the modern web documentation) although I can't find a commit about it so maybe that's just a documentation issue.
In any case, `{branches}` seems to never be useful: `{branch}` provides the same information without the awkward "default-if-empty" case.
Switch from `{branches}` to either `{branch}` (where that's good enough, notably in the hook engine) or `(descendants(%s) and head())`, which is equivalent to `--contains` in Git.
This fixes pushing to branches with spaces in their names, and makes the "Branches" / "Contains" queries moderately more consistent.
Test Plan:
- Pushed to a Mercurial branch with a space in it.
- Viewed list of branches in a Mercurial repository.
- Viewed containing branches of a Mercurial commit in Diffusion.
Reviewers: btrahan
Reviewed By: btrahan
Subscribers: epriestley
Maniphest Tasks: T5304
Differential Revision: https://secure.phabricator.com/D9453
2014-06-20 20:48:31 +02:00
|
|
|
$query->withContainsCommit($contains);
|
2014-01-18 01:11:04 +01:00
|
|
|
}
|
|
|
|
|
Never use "{branches}" in Mercurial
Summary:
Fixes T5304. Mercurial features a "{branches}" template keyword, documented as:
```
branches List of strings. The name of the branch on which the
changeset was committed. Will be empty if the branch name
was default.
```
At some time long in the past, I misinterpreted this to mean "list of branches where the branch head is a descendant of the commit". It is more like "list of zero or one elements, possibly containing the name of the branch the commit was originally made to, if that branch was not 'default'".
In fact, it seems like this is because a //very// long time in the past, Mercurial worked roughly like I expected:
> Ages ago (2005), we had a very different and ultimately unworkable
> approach to named branches that worked vaguely like .hgtags and allowed
> multiple branch names per revision.
http://marc.info/?l=mercurial-devel&m=129883069414855
This appears to be deprecated in modern Mercurial (it's not in the modern web documentation) although I can't find a commit about it so maybe that's just a documentation issue.
In any case, `{branches}` seems to never be useful: `{branch}` provides the same information without the awkward "default-if-empty" case.
Switch from `{branches}` to either `{branch}` (where that's good enough, notably in the hook engine) or `(descendants(%s) and head())`, which is equivalent to `--contains` in Git.
This fixes pushing to branches with spaces in their names, and makes the "Branches" / "Contains" queries moderately more consistent.
Test Plan:
- Pushed to a Mercurial branch with a space in it.
- Viewed list of branches in a Mercurial repository.
- Viewed containing branches of a Mercurial commit in Diffusion.
Reviewers: btrahan
Reviewed By: btrahan
Subscribers: epriestley
Maniphest Tasks: T5304
Differential Revision: https://secure.phabricator.com/D9453
2014-06-20 20:48:31 +02:00
|
|
|
$refs = $query->execute();
|
|
|
|
|
2014-01-18 01:10:56 +01:00
|
|
|
return $this->processBranchRefs($request, $refs);
|
2013-05-01 23:56:36 +02:00
|
|
|
}
|
|
|
|
|
2014-01-29 16:29:35 +01:00
|
|
|
protected function getSVNResult(ConduitAPIRequest $request) {
|
2014-01-28 23:43:13 +01:00
|
|
|
// Since SVN doesn't have meaningful branches, just return nothing for all
|
|
|
|
// queries.
|
|
|
|
return array();
|
|
|
|
}
|
|
|
|
|
2014-01-18 01:10:56 +01:00
|
|
|
private function processBranchRefs(ConduitAPIRequest $request, array $refs) {
|
2013-05-01 23:56:36 +02:00
|
|
|
$drequest = $this->getDiffusionRequest();
|
|
|
|
$repository = $drequest->getRepository();
|
|
|
|
$offset = $request->getValue('offset');
|
|
|
|
$limit = $request->getValue('limit');
|
|
|
|
|
2014-01-18 01:10:56 +01:00
|
|
|
foreach ($refs as $key => $ref) {
|
|
|
|
if (!$repository->shouldTrackBranch($ref->getShortName())) {
|
|
|
|
unset($refs[$key]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-04-27 12:51:21 +02:00
|
|
|
$with_closed = $request->getValue('closed');
|
|
|
|
if ($with_closed !== null) {
|
|
|
|
foreach ($refs as $key => $ref) {
|
|
|
|
$fields = $ref->getRawFields();
|
|
|
|
if (idx($fields, 'closed') != $with_closed) {
|
|
|
|
unset($refs[$key]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-01-18 01:10:56 +01:00
|
|
|
// NOTE: We can't apply the offset or limit until here, because we may have
|
|
|
|
// filtered untrackable branches out of the result set.
|
2013-05-01 23:56:36 +02:00
|
|
|
|
|
|
|
if ($offset) {
|
2014-01-18 01:10:56 +01:00
|
|
|
$refs = array_slice($refs, $offset);
|
2013-05-01 23:56:36 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
if ($limit) {
|
2014-01-18 01:10:56 +01:00
|
|
|
$refs = array_slice($refs, 0, $limit);
|
2013-05-01 23:56:36 +02:00
|
|
|
}
|
|
|
|
|
2014-01-18 01:10:56 +01:00
|
|
|
return mpull($refs, 'toDictionary');
|
2013-05-01 23:56:36 +02:00
|
|
|
}
|
2014-01-28 23:43:13 +01:00
|
|
|
|
2013-05-01 23:56:36 +02:00
|
|
|
}
|