Page Menu
Home
Phabricator
Search
Configure Global Search
Log In
Files
F15461269
D15482.id37308.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Flag For Later
Size
7 KB
Referenced Files
None
Subscribers
None
D15482.id37308.diff
View Options
diff --git a/src/__phutil_library_map__.php b/src/__phutil_library_map__.php
--- a/src/__phutil_library_map__.php
+++ b/src/__phutil_library_map__.php
@@ -633,6 +633,8 @@
'DiffusionGitBranch' => 'applications/diffusion/data/DiffusionGitBranch.php',
'DiffusionGitBranchTestCase' => 'applications/diffusion/data/__tests__/DiffusionGitBranchTestCase.php',
'DiffusionGitFileContentQuery' => 'applications/diffusion/query/filecontent/DiffusionGitFileContentQuery.php',
+ 'DiffusionGitLFSAuthenticateWorkflow' => 'applications/diffusion/gitlfs/DiffusionGitLFSAuthenticateWorkflow.php',
+ 'DiffusionGitLFSTemporaryTokenType' => 'applications/diffusion/gitlfs/DiffusionGitLFSTemporaryTokenType.php',
'DiffusionGitRawDiffQuery' => 'applications/diffusion/query/rawdiff/DiffusionGitRawDiffQuery.php',
'DiffusionGitReceivePackSSHWorkflow' => 'applications/diffusion/ssh/DiffusionGitReceivePackSSHWorkflow.php',
'DiffusionGitRequest' => 'applications/diffusion/request/DiffusionGitRequest.php',
@@ -4760,6 +4762,8 @@
'DiffusionGitBranch' => 'Phobject',
'DiffusionGitBranchTestCase' => 'PhabricatorTestCase',
'DiffusionGitFileContentQuery' => 'DiffusionFileContentQuery',
+ 'DiffusionGitLFSAuthenticateWorkflow' => 'DiffusionGitSSHWorkflow',
+ 'DiffusionGitLFSTemporaryTokenType' => 'PhabricatorAuthTemporaryTokenType',
'DiffusionGitRawDiffQuery' => 'DiffusionRawDiffQuery',
'DiffusionGitReceivePackSSHWorkflow' => 'DiffusionGitSSHWorkflow',
'DiffusionGitRequest' => 'DiffusionRequest',
diff --git a/src/applications/diffusion/gitlfs/DiffusionGitLFSAuthenticateWorkflow.php b/src/applications/diffusion/gitlfs/DiffusionGitLFSAuthenticateWorkflow.php
new file mode 100644
--- /dev/null
+++ b/src/applications/diffusion/gitlfs/DiffusionGitLFSAuthenticateWorkflow.php
@@ -0,0 +1,118 @@
+<?php
+
+final class DiffusionGitLFSAuthenticateWorkflow
+ extends DiffusionGitSSHWorkflow {
+
+ protected function didConstruct() {
+ $this->setName('git-lfs-authenticate');
+ $this->setArguments(
+ array(
+ array(
+ 'name' => 'argv',
+ 'wildcard' => true,
+ ),
+ ));
+ }
+
+ protected function identifyRepository() {
+ return $this->loadRepositoryWithPath($this->getLFSPathArgument());
+ }
+
+ private function getLFSPathArgument() {
+ return $this->getLFSArgument(0);
+ }
+
+ private function getLFSOperationArgument() {
+ return $this->getLFSArgument(1);
+ }
+
+ private function getLFSArgument($position) {
+ $args = $this->getArgs();
+ $argv = $args->getArg('argv');
+
+ if (!isset($argv[$position])) {
+ throw new Exception(
+ pht(
+ 'Expected `git-lfs-authenticate <path> <operation>`, but received '.
+ 'too few arguments.'));
+ }
+
+ return $argv[$position];
+ }
+
+ protected function executeRepositoryOperations() {
+ $operation = $this->getLFSOperationArgument();
+
+ // NOTE: We aren't checking write access here, even for "upload". The
+ // HTTP endpoint should be able to do that for us.
+
+ switch ($operation) {
+ case 'upload':
+ case 'download':
+ break;
+ default:
+ throw new Exception(
+ pht(
+ 'Git LFS operation "%s" is not supported by this server.',
+ $operation));
+ }
+
+ $repository = $this->getRepository();
+
+ if (!$repository->isGit()) {
+ throw new Exception(
+ pht(
+ 'Repository "%s" is not a Git repository. Git LFS is only '.
+ 'supported for Git repositories.',
+ $repository->getDisplayName()));
+ }
+
+ if (!$repository->canUseGitLFS()) {
+ throw new Exception(
+ pht('Git LFS is not enabled for this repository.'));
+ }
+
+ // NOTE: This is usually the same as the default URI (which does not
+ // need to be specified in the response), but the protocol or domain may
+ // differ in some situations.
+
+ $lfs_uri = $repository->getGitLFSURI('info/lfs');
+
+ // Generate a temporary token to allow the user to acces LFS over HTTP.
+ // This works even if normal HTTP repository operations are not available
+ // on this host, and does not require the user to have a VCS password.
+
+ $user = $this->getUser();
+ $headers = array();
+
+ $lfs_user = DiffusionGitLFSTemporaryTokenType::HTTP_USERNAME;
+ $lfs_pass = Filesystem::readRandomCharacters(32);
+ $lfs_hash = PhabricatorHash::digest($lfs_pass);
+
+ $ttl = PhabricatorTime::getNow() + phutil_units('1 day in seconds');
+
+ $token = id(new PhabricatorAuthTemporaryToken())
+ ->setTokenResource($repository->getPHID())
+ ->setTokenType(DiffusionGitLFSTemporaryTokenType::TOKENTYPE)
+ ->setTokenCode($lfs_hash)
+ ->setUserPHID($user->getPHID())
+ ->setTemporaryTokenProperty('lfs.operation', $operation)
+ ->setTokenExpires($ttl)
+ ->save();
+
+ $authorization_header = base64_encode($lfs_user.':'.$lfs_pass);
+ $headers['Authorization'] = 'Basic '.$authorization_header;
+
+ $result = array(
+ 'header' => $headers,
+ 'href' => $lfs_uri,
+ );
+ $result = phutil_json_encode($result);
+
+ $this->writeIO($result);
+ $this->waitForGitClient();
+
+ return 0;
+ }
+
+}
diff --git a/src/applications/diffusion/gitlfs/DiffusionGitLFSTemporaryTokenType.php b/src/applications/diffusion/gitlfs/DiffusionGitLFSTemporaryTokenType.php
new file mode 100644
--- /dev/null
+++ b/src/applications/diffusion/gitlfs/DiffusionGitLFSTemporaryTokenType.php
@@ -0,0 +1,18 @@
+<?php
+
+final class DiffusionGitLFSTemporaryTokenType
+ extends PhabricatorAuthTemporaryTokenType {
+
+ const TOKENTYPE = 'diffusion.git.lfs';
+ const HTTP_USERNAME = '@git-lfs';
+
+ public function getTokenTypeDisplayName() {
+ return pht('Git Large File Storage');
+ }
+
+ public function getTokenReadableTypeName(
+ PhabricatorAuthTemporaryToken $token) {
+ return pht('Git LFS Token');
+ }
+
+}
diff --git a/src/applications/repository/storage/PhabricatorRepository.php b/src/applications/repository/storage/PhabricatorRepository.php
--- a/src/applications/repository/storage/PhabricatorRepository.php
+++ b/src/applications/repository/storage/PhabricatorRepository.php
@@ -1518,6 +1518,10 @@
return null;
}
+ return $this->getRawHTTPCloneURIObject();
+ }
+
+ private function getRawHTTPCloneURIObject() {
$uri = PhabricatorEnv::getProductionURI($this->getURI());
$uri = new PhutilURI($uri);
@@ -1819,6 +1823,38 @@
return !$this->isSVN();
}
+ public function canUseGitLFS() {
+ if (!$this->isGit()) {
+ return false;
+ }
+
+ if (!$this->isHosted()) {
+ return false;
+ }
+
+ // TODO: Unprototype this feature.
+ if (!PhabricatorEnv::getEnvConfig('phabricator.show-prototypes')) {
+ return false;
+ }
+
+ return true;
+ }
+
+ public function getGitLFSURI($path = null) {
+ if (!$this->canUseGitLFS()) {
+ throw new Exception(
+ pht(
+ 'This repository does not support Git LFS, so Git LFS URIs can '.
+ 'not be generated for it.'));
+ }
+
+ $uri = $this->getRawHTTPCloneURIObject();
+ $uri = (string)$uri;
+ $uri = $uri.'/'.$path;
+
+ return $uri;
+ }
+
public function canMirror() {
if ($this->isGit() || $this->isHg()) {
return true;
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Wed, Apr 2, 6:52 AM (5 d, 17 h ago)
Storage Engine
blob
Storage Format
Encrypted (AES-256-CBC)
Storage Handle
7390389
Default Alt Text
D15482.id37308.diff (7 KB)
Attached To
Mode
D15482: Implement "git-lfs-authenticate" over SSH
Attached
Detach File
Event Timeline
Log In to Comment