mirror of
https://we.phorge.it/source/phorge.git
synced 2024-12-22 05:20:56 +01:00
Make Diffusion do an alright job on Git LFS objects
Summary: Ref T7789. This isn't the most perfect UI imaginable, but it's similar to what GitHub does and seems reasonable. Test Plan: {F1180271} {F1180272} Reviewers: chad Reviewed By: chad Maniphest Tasks: T7789 Differential Revision: https://secure.phabricator.com/D15494
This commit is contained in:
parent
78e36d6b17
commit
61ab7afc9c
1 changed files with 125 additions and 2 deletions
|
@ -192,7 +192,25 @@ final class DiffusionBrowseController extends DiffusionController {
|
||||||
}
|
}
|
||||||
|
|
||||||
$data = $file->loadFileData();
|
$data = $file->loadFileData();
|
||||||
if (ArcanistDiffUtils::isHeuristicBinaryFile($data)) {
|
|
||||||
|
$ref = $this->getGitLFSRef($repository, $data);
|
||||||
|
if ($ref) {
|
||||||
|
if ($view == 'git-lfs') {
|
||||||
|
$file = $this->loadGitLFSFile($ref);
|
||||||
|
|
||||||
|
// Rename the file locally so we generate a better vanity URI for
|
||||||
|
// it. In storage, it just has a name like "lfs-13f9a94c0923...",
|
||||||
|
// since we don't get any hints about possible human-readable names
|
||||||
|
// at upload time.
|
||||||
|
$basename = basename($drequest->getPath());
|
||||||
|
$file->makeEphemeral();
|
||||||
|
$file->setName($basename);
|
||||||
|
|
||||||
|
return $file->getRedirectResponse();
|
||||||
|
} else {
|
||||||
|
$corpus = $this->buildGitLFSCorpus($ref);
|
||||||
|
}
|
||||||
|
} else if (ArcanistDiffUtils::isHeuristicBinaryFile($data)) {
|
||||||
$file_uri = $file->getBestURI();
|
$file_uri = $file->getBestURI();
|
||||||
|
|
||||||
if ($file->isViewableImage()) {
|
if ($file->isViewableImage()) {
|
||||||
|
@ -930,7 +948,7 @@ final class DiffusionBrowseController extends DiffusionController {
|
||||||
return $button;
|
return $button;
|
||||||
}
|
}
|
||||||
|
|
||||||
private function renderFileButton($file_uri = null) {
|
private function renderFileButton($file_uri = null, $label = null) {
|
||||||
|
|
||||||
$base_uri = $this->getRequest()->getRequestURI();
|
$base_uri = $this->getRequest()->getRequestURI();
|
||||||
|
|
||||||
|
@ -944,6 +962,10 @@ final class DiffusionBrowseController extends DiffusionController {
|
||||||
$icon = 'fa-file-text';
|
$icon = 'fa-file-text';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ($label !== null) {
|
||||||
|
$text = $label;
|
||||||
|
}
|
||||||
|
|
||||||
$button = id(new PHUIButtonView())
|
$button = id(new PHUIButtonView())
|
||||||
->setTag('a')
|
->setTag('a')
|
||||||
->setText($text)
|
->setText($text)
|
||||||
|
@ -953,6 +975,21 @@ final class DiffusionBrowseController extends DiffusionController {
|
||||||
return $button;
|
return $button;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private function renderGitLFSButton() {
|
||||||
|
$viewer = $this->getViewer();
|
||||||
|
|
||||||
|
$uri = $this->getRequest()->getRequestURI();
|
||||||
|
$href = $uri->alter('view', 'git-lfs');
|
||||||
|
|
||||||
|
$text = pht('Download from Git LFS');
|
||||||
|
$icon = 'fa-download';
|
||||||
|
|
||||||
|
return id(new PHUIButtonView())
|
||||||
|
->setTag('a')
|
||||||
|
->setText($text)
|
||||||
|
->setHref($href)
|
||||||
|
->setIcon($icon);
|
||||||
|
}
|
||||||
|
|
||||||
private function buildDisplayRows(
|
private function buildDisplayRows(
|
||||||
array $lines,
|
array $lines,
|
||||||
|
@ -1889,4 +1926,90 @@ final class DiffusionBrowseController extends DiffusionController {
|
||||||
$corpus);
|
$corpus);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private function getGitLFSRef(PhabricatorRepository $repository, $data) {
|
||||||
|
if (!$repository->canUseGitLFS()) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
$lfs_pattern = '(^version https://git-lfs\\.github\\.com/spec/v1[\r\n])';
|
||||||
|
if (!preg_match($lfs_pattern, $data)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
$matches = null;
|
||||||
|
if (!preg_match('(^oid sha256:(.*)$)m', $data, $matches)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
$hash = $matches[1];
|
||||||
|
$hash = trim($hash);
|
||||||
|
|
||||||
|
return id(new PhabricatorRepositoryGitLFSRefQuery())
|
||||||
|
->setViewer($this->getViewer())
|
||||||
|
->withRepositoryPHIDs(array($repository->getPHID()))
|
||||||
|
->withObjectHashes(array($hash))
|
||||||
|
->executeOne();
|
||||||
|
}
|
||||||
|
|
||||||
|
private function buildGitLFSCorpus(PhabricatorRepositoryGitLFSRef $ref) {
|
||||||
|
// TODO: We should probably test if we can load the file PHID here and
|
||||||
|
// show the user an error if we can't, rather than making them click
|
||||||
|
// through to hit an error.
|
||||||
|
|
||||||
|
$header = id(new PHUIHeaderView())
|
||||||
|
->setHeader(basename($this->getDiffusionRequest()->getPath()))
|
||||||
|
->setHeaderIcon('fa-archive');
|
||||||
|
|
||||||
|
$severity = PHUIInfoView::SEVERITY_NOTICE;
|
||||||
|
|
||||||
|
$messages = array();
|
||||||
|
$messages[] = pht(
|
||||||
|
'This %s file is stored in Git Large File Storage.',
|
||||||
|
phutil_format_bytes($ref->getByteSize()));
|
||||||
|
|
||||||
|
try {
|
||||||
|
$file = $this->loadGitLFSFile($ref);
|
||||||
|
$data = $this->renderGitLFSButton();
|
||||||
|
$header->addActionLink($data);
|
||||||
|
} catch (Exception $ex) {
|
||||||
|
$severity = PHUIInfoView::SEVERITY_ERROR;
|
||||||
|
$messages[] = pht('The data for this file could not be loaded.');
|
||||||
|
}
|
||||||
|
|
||||||
|
$raw = $this->renderFileButton(null, pht('View Raw LFS Pointer'));
|
||||||
|
$header->addActionLink($raw);
|
||||||
|
|
||||||
|
$corpus = id(new PHUIObjectBoxView())
|
||||||
|
->setHeader($header)
|
||||||
|
->setBackground(PHUIObjectBoxView::BLUE_PROPERTY)
|
||||||
|
->setCollapsed(true);
|
||||||
|
|
||||||
|
if ($messages) {
|
||||||
|
$corpus->setInfoView(
|
||||||
|
id(new PHUIInfoView())
|
||||||
|
->setSeverity($severity)
|
||||||
|
->setErrors($messages));
|
||||||
|
}
|
||||||
|
|
||||||
|
return $corpus;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function loadGitLFSFile(PhabricatorRepositoryGitLFSRef $ref) {
|
||||||
|
$viewer = $this->getViewer();
|
||||||
|
|
||||||
|
$file = id(new PhabricatorFileQuery())
|
||||||
|
->setViewer($viewer)
|
||||||
|
->withPHIDs(array($ref->getFilePHID()))
|
||||||
|
->executeOne();
|
||||||
|
if (!$file) {
|
||||||
|
throw new Exception(
|
||||||
|
pht(
|
||||||
|
'Failed to load file object for Git LFS ref "%s"!',
|
||||||
|
$ref->getObjectHash()));
|
||||||
|
}
|
||||||
|
|
||||||
|
return $file;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue