diff --git a/src/applications/repository/daemon/PhabricatorRepositoryPullLocalDaemon.php b/src/applications/repository/daemon/PhabricatorRepositoryPullLocalDaemon.php index 4c22b30000..87e328949b 100644 --- a/src/applications/repository/daemon/PhabricatorRepositoryPullLocalDaemon.php +++ b/src/applications/repository/daemon/PhabricatorRepositoryPullLocalDaemon.php @@ -536,20 +536,22 @@ final class PhabricatorRepositoryPullLocalDaemon private function executeGitDiscover( PhabricatorRepository $repository) { - list($remotes) = $repository->execxLocalCommand( - 'remote show -n origin'); + if (!$repository->isHosted()) { + list($remotes) = $repository->execxLocalCommand( + 'remote show -n origin'); - $matches = null; - if (!preg_match('/^\s*Fetch URL:\s*(.*?)\s*$/m', $remotes, $matches)) { - throw new Exception( - "Expected 'Fetch URL' in 'git remote show -n origin'."); + $matches = null; + if (!preg_match('/^\s*Fetch URL:\s*(.*?)\s*$/m', $remotes, $matches)) { + throw new Exception( + "Expected 'Fetch URL' in 'git remote show -n origin'."); + } + + self::executeGitVerifySameOrigin( + $matches[1], + $repository->getRemoteURI(), + $repository->getLocalPath()); } - self::executeGitVerifySameOrigin( - $matches[1], - $repository->getRemoteURI(), - $repository->getLocalPath()); - $refs = id(new DiffusionLowLevelGitRefQuery()) ->setRepository($repository) ->withIsOriginBranch(true) @@ -744,6 +746,11 @@ final class PhabricatorRepositoryPullLocalDaemon // NOTE: "--debug" gives us 40-character hashes. list($stdout) = $repository->execxLocalCommand('--debug branches'); + if (!trim($stdout)) { + // No branches; likely a newly initialized repository. + return false; + } + $branches = ArcanistMercurialParser::parseMercurialBranches($stdout); $got_something = false; foreach ($branches as $name => $branch) { diff --git a/src/applications/repository/engine/PhabricatorRepositoryPullEngine.php b/src/applications/repository/engine/PhabricatorRepositoryPullEngine.php index 2fa02c6832..154ca4342f 100644 --- a/src/applications/repository/engine/PhabricatorRepositoryPullEngine.php +++ b/src/applications/repository/engine/PhabricatorRepositoryPullEngine.php @@ -5,9 +5,13 @@ * @{class:PhabricatorRepository} objects. Used by * @{class:PhabricatorRepositoryPullLocalDaemon}. * + * This class also covers initial working copy setup through `git clone`, + * `git init`, `hg clone`, `hg init`, or `svnadmin create`. + * * @task pull Pulling Working Copies * @task git Pulling Git Working Copies * @task hg Pulling Mercurial Working Copies + * @task svn Pulling Subversion Working Copies * @task internal Internals */ final class PhabricatorRepositoryPullEngine @@ -22,28 +26,24 @@ final class PhabricatorRepositoryPullEngine $is_hg = false; $is_git = false; + $is_svn = true; $vcs = $repository->getVersionControlSystem(); $callsign = $repository->getCallsign(); - if ($repository->isHosted()) { - $this->skipPull( - pht( - 'Repository "%s" is hosted, so Phabricator does not pull updates '. - 'for it.', - $callsign)); - return; - } - switch ($vcs) { case PhabricatorRepositoryType::REPOSITORY_TYPE_SVN: - // We never pull a local copy of Subversion repositories. - $this->skipPull( - pht( - "Repository '%s' is a Subversion repository, which does not ". - "require a local working copy to be pulled.", - $callsign)); - return; + // We never pull a local copy of non-hosted Subversion repositories. + if (!$repository->isHosted()) { + $this->skipPull( + pht( + "Repository '%s' is a non-hosted Subversion repository, which ". + "does not require a local working copy to be pulled.", + $callsign)); + return; + } + $is_svn = true; + break; case PhabricatorRepositoryType::REPOSITORY_TYPE_GIT: $is_git = true; break; @@ -76,18 +76,28 @@ final class PhabricatorRepositoryPullEngine $callsign)); if ($is_git) { $this->executeGitCreate(); - } else { + } else if ($is_hg) { $this->executeMercurialCreate(); + } else { + $this->executeSubversionCreate(); } } else { - $this->logPull( - pht( - "Updating the working copy for repository '%s'.", - $callsign)); - if ($is_git) { - $this->executeGitUpdate(); + if ($repository->isHosted()) { + $this->logPull( + pht( + "Repository '%s' is hosted, so Phabricator does not pull ". + "updates for it.", + $callsign)); } else { - $this->executeMercurialUpdate(); + $this->logPull( + pht( + "Updating the working copy for repository '%s'.", + $callsign)); + if ($is_git) { + $this->executeGitUpdate(); + } else { + $this->executeMercurialUpdate(); + } } } } catch (Exception $ex) { @@ -102,8 +112,8 @@ final class PhabricatorRepositoryPullEngine } private function skipPull($message) { - $this->updateRepositoryInitStatus(null); $this->log('%s', $message); + $this->donePull(); } private function abortPull($message, Exception $ex = null) { @@ -146,10 +156,18 @@ final class PhabricatorRepositoryPullEngine private function executeGitCreate() { $repository = $this->getRepository(); - $repository->execxRemoteCommand( - 'clone --bare %s %s', - $repository->getRemoteURI(), - rtrim($repository->getLocalPath(), '/')); + $path = rtrim($repository->getLocalPath(), '/'); + + if ($repository->isHosted()) { + $repository->execxRemoteCommand( + 'init --bare -- %s', + $path); + } else { + $repository->execxRemoteCommand( + 'clone --bare -- %s %s', + $repository->getRemoteURI(), + $path); + } } @@ -270,10 +288,18 @@ final class PhabricatorRepositoryPullEngine private function executeMercurialCreate() { $repository = $this->getRepository(); - $repository->execxRemoteCommand( - 'clone %s %s', - $repository->getRemoteURI(), - rtrim($repository->getLocalPath(), '/')); + $path = rtrim($repository->getLocalPath(), '/'); + + if ($repository->isHosted()) { + $repository->execxRemoteCommand( + 'init -- %s', + $path); + } else { + $repository->execxRemoteCommand( + 'clone -- %s %s', + $repository->getRemoteURI(), + $path); + } } @@ -318,6 +344,20 @@ final class PhabricatorRepositoryPullEngine } +/* -( Pulling Subversion Working Copies )---------------------------------- */ + + + /** + * @task svn + */ + private function executeSubversionCreate() { + $repository = $this->getRepository(); + + $path = rtrim($repository->getLocalPath(), '/'); + execx('svnadmin create -- %s', $path); + } + + /* -( Internals )---------------------------------------------------------- */ diff --git a/src/applications/repository/storage/PhabricatorRepository.php b/src/applications/repository/storage/PhabricatorRepository.php index 1db2a5cc41..2174bdbadf 100644 --- a/src/applications/repository/storage/PhabricatorRepository.php +++ b/src/applications/repository/storage/PhabricatorRepository.php @@ -161,8 +161,16 @@ final class PhabricatorRepository extends PhabricatorRepositoryDAO throw new Exception("Not a subversion repository!"); } - $uri = $this->getDetail('remote-uri'); + if ($this->isHosted()) { + $uri = 'file://'.$this->getLocalPath(); + } else { + $uri = $this->getDetail('remote-uri'); + } + $subpath = $this->getDetail('svn-subpath'); + if ($subpath) { + $subpath = '/'.ltrim($subpath, '/'); + } return $uri.$subpath; } @@ -609,6 +617,10 @@ final class PhabricatorRepository extends PhabricatorRepositoryDAO * @task uri */ private function shouldUseSSH() { + if ($this->isHosted()) { + return false; + } + $protocol = $this->getRemoteProtocol(); if ($this->isSSHProtocol($protocol)) { return (bool)$this->getSSHKeyfile(); @@ -626,6 +638,10 @@ final class PhabricatorRepository extends PhabricatorRepositoryDAO * @task uri */ private function shouldUseHTTP() { + if ($this->isHosted()) { + return false; + } + $protocol = $this->getRemoteProtocol(); if ($protocol == 'http' || $protocol == 'https') { return (bool)$this->getDetail('http-login'); @@ -643,6 +659,10 @@ final class PhabricatorRepository extends PhabricatorRepositoryDAO * @task uri */ private function shouldUseSVNProtocol() { + if ($this->isHosted()) { + return false; + } + $protocol = $this->getRemoteProtocol(); if ($protocol == 'svn') { return (bool)$this->getDetail('http-login'); @@ -788,14 +808,8 @@ final class PhabricatorRepository extends PhabricatorRepositoryDAO * Raise more useful errors when there are basic filesystem problems. */ private function assertLocalExists() { - switch ($this->getVersionControlSystem()) { - case PhabricatorRepositoryType::REPOSITORY_TYPE_SVN: - if (!$this->isHosted()) { - // For non-hosted SVN repositories, we don't expect a local directory - // to exist. - return; - } - break; + if (!$this->usesLocalWorkingCopy()) { + return; } $local = $this->getLocalPath();