Skip to content

Commit 5c3b1e6

Browse files
committed
Fixes #17 by better resolving recipe repo urls
1 parent b14a60d commit 5c3b1e6

File tree

6 files changed

+162
-30
lines changed

6 files changed

+162
-30
lines changed

assets/js/dashboard.js

Lines changed: 2 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -80,31 +80,10 @@ let vm = new Vue({
8080
})
8181
},
8282
recipeUrl (recipe) {
83-
return this.buildRecipeRepoUrl(recipe) + '/' + recipe.version
83+
return recipe.publicUrl + '/' + recipe.version
8484
},
8585
recipeVersionUrl (recipe, version) {
86-
return this.buildRecipeRepoUrl(recipe) + '/' + version
87-
},
88-
buildRecipeRepoUrl (recipe) {
89-
let repoUrl, pattern, gitServerHostName
90-
91-
repoUrl = recipe.repo.url.replace('.git', '')
92-
93-
pattern = /^git\@[a-z.]*\:/
94-
if (pattern.test(repoUrl)) {
95-
gitServerHostName = pattern.exec(repoUrl)[0].replace('git@', '').replace(':', '')
96-
repoUrl = repoUrl.replace(pattern, 'https://' + gitServerHostName + '/')
97-
}
98-
99-
pattern = /^https?\:\/\/[a-z.]*/
100-
gitServerHostName = pattern.exec(repoUrl)[0].replace(/https?\:\/\//, '')
101-
102-
switch (gitServerHostName) {
103-
case 'bitbucket.org':
104-
return repoUrl + '/src/master/' + recipe.officialPackageName
105-
default:
106-
return repoUrl + '/tree/master/' + recipe.officialPackageName
107-
}
86+
return recipe.publicUrl + '/' + version
10887
},
10988
showSearch () {
11089
this.enableFilter = true;

public/build/dashboard.5e02d380f9d70724d94b.js renamed to public/build/dashboard.93b73cbfd99ca32ad3c4.js

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

public/build/manifest.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
{
22
"build/dashboard.css": "/build/dashboard.b1963f9d56ce5d23c3b365942619a02a.css",
3-
"build/dashboard.js": "/build/dashboard.5e02d380f9d70724d94b.js"
3+
"build/dashboard.js": "/build/dashboard.93b73cbfd99ca32ad3c4.js"
44
}

src/Entity/Recipe.php

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,9 @@ class Recipe implements \JsonSerializable
4040
*/
4141
private $repo;
4242

43+
/** @var string */
44+
private $publicUrl;
45+
4346
/**
4447
* @var string
4548
*/
@@ -92,7 +95,7 @@ public function setPackage(string $package)
9295
*/
9396
public function getOfficialPackageName()
9497
{
95-
return join('/', [$this->author, $this->package]);
98+
return implode('/', [$this->author, $this->package]);
9699
}
97100

98101
/**
@@ -191,6 +194,22 @@ public function setManifestValid(bool $manifestValid)
191194
$this->manifestValid = $manifestValid;
192195
}
193196

197+
/**
198+
* @return string
199+
*/
200+
public function getPublicUrl(): string
201+
{
202+
return $this->publicUrl;
203+
}
204+
205+
/**
206+
* @param string $publicUrl
207+
*/
208+
public function setPublicUrl(string $publicUrl): void
209+
{
210+
$this->publicUrl = $publicUrl;
211+
}
212+
194213
/**
195214
* @return array
196215
*/
@@ -203,9 +222,10 @@ public function jsonSerialize()
203222
'version' => $this->getVersion(),
204223
'manifest' => $this->getManifest(),
205224
'manifestValid' => $this->isManifestValid(),
206-
'repo' => $this->getRepo()
225+
'repo' => $this->getRepo(),
226+
'publicUrl' => $this->getPublicUrl()
207227
];
208228
}
209229

210230

211-
}
231+
}

src/Service/Compiler/LocalRecipeCompiler.php

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
namespace App\Service\Compiler;
1313

1414
use App\Entity\Recipe;
15+
use App\Service\RecipePublicUrlResolver;
1516
use App\Service\RecipeRepoManager;
1617

1718
/**
@@ -26,6 +27,11 @@ class LocalRecipeCompiler
2627
*/
2728
private $repoManager;
2829

30+
/**
31+
* @var RecipePublicUrlResolver
32+
*/
33+
private $urlResolver;
34+
2935
/**
3036
* @var Recipe[]
3137
*/
@@ -35,9 +41,10 @@ class LocalRecipeCompiler
3541
* LocalRecipeCompiler constructor.
3642
* @param RecipeRepoManager $repoManager
3743
*/
38-
public function __construct(RecipeRepoManager $repoManager)
44+
public function __construct(RecipeRepoManager $repoManager, RecipePublicUrlResolver $urlResolver)
3945
{
4046
$this->repoManager = $repoManager;
47+
$this->urlResolver = $urlResolver;
4148
}
4249

4350
/**
@@ -95,6 +102,8 @@ private function loadLocalRecipes()
95102
$recipe->setRepoSlug($repo->getRepoDirName());
96103
$recipe->setLocalPath($recipeFolder->getPathname());
97104

105+
$recipe->setPublicUrl($this->urlResolver->resolveUrl($recipe));
106+
98107
$manifestFile = $recipeFolder->getPathname() . '/manifest.json';
99108
if (file_exists($manifestFile)) {
100109
$manifest = json_decode(file_get_contents($manifestFile), true);
@@ -110,4 +119,4 @@ private function loadLocalRecipes()
110119
}
111120
}
112121
}
113-
}
122+
}
Lines changed: 124 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,124 @@
1+
<?php
2+
3+
namespace App\Service;
4+
5+
use App\Entity\Recipe;
6+
7+
/**
8+
* Class RecipePublicUrlResolver.
9+
*
10+
* @author Manuel Voss <[email protected]>
11+
*/
12+
class RecipePublicUrlResolver
13+
{
14+
const RECIPE_PREFIXES = [
15+
'bitbucket.org' => '/src/master/',
16+
'default' => '/tree/master/',
17+
];
18+
19+
/**
20+
* @param Recipe $recipe
21+
* @return string
22+
*/
23+
public function resolveUrl(Recipe $recipe)
24+
{
25+
if (null === $recipe->getRepo()) {
26+
throw new \InvalidArgumentException('Recipes must have a repo in order to have their url resolved.');
27+
}
28+
29+
$repoUrl = $recipe->getRepo()->getRepoUrl();
30+
$urlProtocol = parse_url($repoUrl, PHP_URL_SCHEME);
31+
32+
switch ($urlProtocol){
33+
case 'http':
34+
case 'https':
35+
return $this->resolveHttpUrl($repoUrl, $recipe->getOfficialPackageName());
36+
case 'ssh':
37+
return $this->resolveSshUrl($repoUrl, $recipe->getOfficialPackageName());
38+
case null:
39+
if ('git@' === substr($repoUrl, 0, 4)) {
40+
return $this->resolveSshUrl($repoUrl, $recipe->getOfficialPackageName());
41+
}
42+
}
43+
44+
return $this->buildFallbackUrl($repoUrl, $recipe->getOfficialPackageName());
45+
}
46+
47+
/**
48+
* @param string $repoUrl
49+
* @param string $packageName
50+
*
51+
* @return string
52+
*/
53+
private function resolveHttpUrl(string $repoUrl, string $packageName)
54+
{
55+
if (preg_match('/^(?:https?(?:\:\/\/)?)?([a-zA-Z0-9-_\.]+\.[a-z]+)(?:\:([0-9]+))?\/([a-zA-Z0-9-_]+)\/([a-zA-Z0-9-_]+)(?:\.git)?$/', $repoUrl,$urlParts)) {
56+
$host = $urlParts[1];
57+
$port = empty($urlParts[2]) ? null : $urlParts[2];
58+
$user = $urlParts[3];
59+
$repo = $urlParts[4];
60+
61+
return $this->buildUrl($host, implode('/', [$user, $repo]), $packageName, $port);
62+
}
63+
64+
return $this->buildFallbackUrl($repoUrl, $packageName);
65+
}
66+
67+
/**
68+
* @param string $repoUrl
69+
* @param string $packageName
70+
*
71+
* @return string
72+
*/
73+
private function resolveSshUrl(string $repoUrl, string $packageName)
74+
{
75+
if (preg_match('/^(?:ssh(?:\:\/\/)?)?(?:git)?\@?([a-zA-Z0-9-_\.]+\.[a-z]+)[:\/](?:([0-9]+)(?:\/))?([a-zA-Z0-9-_]+)\/([a-zA-Z0-9-_]+)(?:\.git)?$/', $repoUrl,$urlParts)) {
76+
$host = $urlParts[1];
77+
$port = empty($urlParts[2]) ? null : $urlParts[2];
78+
$user = $urlParts[3];
79+
$repo = $urlParts[4];
80+
81+
return $this->buildUrl($host, implode('/', [$user, $repo]), $packageName, $port);
82+
}
83+
84+
return $this->buildFallbackUrl($repoUrl, $packageName);
85+
}
86+
87+
/**
88+
* Returns a fallback URL based on best practices used by f.i. github or gitlab
89+
*
90+
* @param string $repoUrl
91+
* @param string $packageName
92+
*
93+
* @return string
94+
*/
95+
private function buildFallbackUrl(string $repoUrl, string $packageName)
96+
{
97+
$host = parse_url($repoUrl, PHP_URL_HOST);
98+
$port = parse_url($repoUrl, PHP_URL_PORT);
99+
$path = parse_url($repoUrl, PHP_URL_PATH);
100+
101+
return $this->buildUrl($host, str_replace('.git', '', $path), $packageName, $port);
102+
}
103+
104+
/**
105+
* @param string $host
106+
* @param string $repo
107+
* @param string $packageName
108+
* @param int|null $port
109+
* @param bool $secure
110+
*
111+
* @return string
112+
*/
113+
private function buildUrl(string $host, string $repo, string $packageName, int $port = null, bool $secure = true)
114+
{
115+
$url = 'http'.($secure?'s':'').'://';
116+
$url .= rtrim($host, '/');
117+
if (null !== $port) {
118+
$url .= ':'.$port;
119+
}
120+
$url .= '/'.$repo.(self::RECIPE_PREFIXES[$host] ?? self::RECIPE_PREFIXES['default']).$packageName;
121+
122+
return $url;
123+
}
124+
}

0 commit comments

Comments
 (0)