From 94a4a532c84978c1ded12960d4d70e5305b1cff9 Mon Sep 17 00:00:00 2001 From: Jory Geerts Date: Wed, 28 Feb 2018 08:47:26 +0100 Subject: [PATCH] Allow mismatches in package names. Fixes #30 Requiring the vendor/package to be the same as the group/project is a good default to help prevent copy-paste errors and such. However, in situations where the GitLab structure is simply different from the vendor/package names, it should be possible to overwrite this behavior. --- README.md | 5 ++-- confs/samples/gitlab.ini | 4 +++ htdocs/packages.php | 65 +++++++++++++++++++++++++++------------- 3 files changed, 52 insertions(+), 22 deletions(-) diff --git a/README.md b/README.md index 9d2ebeb..a4e74ef 100644 --- a/README.md +++ b/README.md @@ -20,9 +20,10 @@ See [example](examples/packages.json). Simply include a composer.json in your project, all branches and tags respecting the [formats for versions](http://getcomposer.org/doc/04-schema.md#version) will be detected. -Only requirement is that the package `name` must be equal to the path of the project. i.e.: `my-group/my-project`. +By default, the package `name` must be equal to the path of the project. i.e.: `my-group/my-project`. This is not a design requirement, it is mostly to prevent common errors when you copy a `composer.json` -from another project without changing its name. +from another project without changing its name. To enable support for differences between package names and project +paths, set `allow_package_name_mismatch` to `true` in `confs/gitlab.ini`. Then, to use your repository, add this in the `composer.json` of your project: ```json diff --git a/confs/samples/gitlab.ini b/confs/samples/gitlab.ini index 99e0854..21475ed 100644 --- a/confs/samples/gitlab.ini +++ b/confs/samples/gitlab.ini @@ -5,6 +5,10 @@ endpoint="http://gitlab.example.com/api/v4/" api_key="ASDFGHJKL12345678" method="ssh" + ; You can restrict to some gitlab groups: ;groups[]="one_group" ;groups[]="other_group" + +; Allow package names to differ from their group/project names in GitLab +;allow_package_name_mismatch=true \ No newline at end of file diff --git a/htdocs/packages.php b/htdocs/packages.php index 39a4226..9a7d560 100644 --- a/htdocs/packages.php +++ b/htdocs/packages.php @@ -48,6 +48,8 @@ define('method', 'ssh'); } +$allow_package_name_mismatches = !empty($confs['allow_package_name_mismatch']); + /** * Retrieves some information about a project's composer.json * @@ -55,7 +57,7 @@ * @param string $ref commit id * @return array|false */ -$fetch_composer = function($project, $ref) use ($repos) { +$fetch_composer = function($project, $ref) use ($repos, $allow_package_name_mismatches) { try { $c = $repos->getFile($project['id'], 'composer.json', $ref); @@ -65,7 +67,7 @@ $composer = json_decode(base64_decode($c['content']), true); - if (empty($composer['name']) || strcasecmp($composer['name'], $project['path_with_namespace']) !== 0) { + if (empty($composer['name']) || (!$allow_package_name_mismatches && strcasecmp($composer['name'], $project['path_with_namespace']) !== 0)) { return false; // packages must have a name and must match } @@ -83,24 +85,33 @@ * @return array [$version => ['name' => $name, 'version' => $version, 'source' => [...]]] */ $fetch_ref = function($project, $ref) use ($fetch_composer) { - if (preg_match('/^v?\d+\.\d+(\.\d+)*(\-(dev|patch|alpha|beta|RC)\d*)?$/', $ref['name'])) { - $version = $ref['name']; - } else { - $version = 'dev-' . $ref['name']; - } - if (($data = $fetch_composer($project, $ref['commit']['id'])) !== false) { - $data['version'] = $version; - $data['source'] = array( - 'url' => $project[method . '_url_to_repo'], - 'type' => 'git', - 'reference' => $ref['commit']['id'], - ); + static $ref_cache = []; - return array($version => $data); - } else { - return array(); + $ref_key = md5(serialize($project) . serialize($ref)); + + if (!isset($ref_cache[$ref_key])) { + if (preg_match('/^v?\d+\.\d+(\.\d+)*(\-(dev|patch|alpha|beta|RC)\d*)?$/', $ref['name'])) { + $version = $ref['name']; + } else { + $version = 'dev-' . $ref['name']; + } + + if (($data = $fetch_composer($project, $ref['commit']['id'])) !== false) { + $data['version'] = $version; + $data['source'] = [ + 'url' => $project[method . '_url_to_repo'], + 'type' => 'git', + 'reference' => $ref['commit']['id'], + ]; + + $ref_cache[$ref_key] = [$version => $data]; + } else { + $ref_cache[$ref_key] = []; + } } + + return $ref_cache[$ref_key]; }; /** @@ -110,7 +121,6 @@ */ $fetch_refs = function($project) use ($fetch_ref, $repos) { $datas = array(); - try { foreach (array_merge($repos->branches($project['id']), $repos->tags($project['id'])) as $ref) { foreach ($fetch_ref($project, $ref) as $version => $data) { @@ -159,6 +169,21 @@ } }; +/** + * Determine the name to use for the package. + * + * @param array $project + * @return string The name of the project + */ +$get_package_name = function($project) use ($allow_package_name_mismatches, $fetch_ref, $repos) { + if ($allow_package_name_mismatches) { + $ref = $fetch_ref($project, $repos->branch($project['id'], $project['default_branch'])); + return reset($ref)['name']; + } + + return $project['path_with_namespace']; +}; + // Load projects $all_projects = array(); $mtime = 0; @@ -190,8 +215,8 @@ if (!file_exists($packages_file) || filemtime($packages_file) < $mtime) { $packages = array(); foreach ($all_projects as $project) { - if ($package = $load_data($project)) { - $packages[$project['path_with_namespace']] = $package; + if (($package = $load_data($project)) && ($package_name = $get_package_name($project))) { + $packages[$package_name] = $package; } } if ( file_exists( $static_file ) ) {