dependabot-composer 0.89.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/helpers/.php_cs +32 -0
- data/helpers/bin/run.php +84 -0
- data/helpers/build +14 -0
- data/helpers/composer.json +14 -0
- data/helpers/composer.lock +1528 -0
- data/helpers/php/.php_cs +34 -0
- data/helpers/setup.sh +4 -0
- data/helpers/src/DependabotInstallationManager.php +61 -0
- data/helpers/src/DependabotPluginManager.php +23 -0
- data/helpers/src/ExceptionIO.php +25 -0
- data/helpers/src/Hasher.php +21 -0
- data/helpers/src/UpdateChecker.php +123 -0
- data/helpers/src/Updater.php +97 -0
- data/lib/dependabot/composer.rb +11 -0
- data/lib/dependabot/composer/file_fetcher.rb +132 -0
- data/lib/dependabot/composer/file_parser.rb +179 -0
- data/lib/dependabot/composer/file_updater.rb +78 -0
- data/lib/dependabot/composer/file_updater/lockfile_updater.rb +267 -0
- data/lib/dependabot/composer/file_updater/manifest_updater.rb +66 -0
- data/lib/dependabot/composer/metadata_finder.rb +68 -0
- data/lib/dependabot/composer/native_helpers.rb +20 -0
- data/lib/dependabot/composer/requirement.rb +98 -0
- data/lib/dependabot/composer/update_checker.rb +176 -0
- data/lib/dependabot/composer/update_checker/requirements_updater.rb +253 -0
- data/lib/dependabot/composer/update_checker/version_resolver.rb +214 -0
- data/lib/dependabot/composer/version.rb +26 -0
- metadata +195 -0
data/helpers/php/.php_cs
ADDED
@@ -0,0 +1,34 @@
|
|
1
|
+
<?php
|
2
|
+
|
3
|
+
$finder = PhpCsFixer\Finder::create()
|
4
|
+
->in(__DIR__ . '/src')
|
5
|
+
->in(__DIR__ . '/bin');
|
6
|
+
|
7
|
+
return PhpCsFixer\Config::create()
|
8
|
+
->setRules([
|
9
|
+
'@Symfony' => true,
|
10
|
+
'array_syntax' => ['syntax' => 'short'],
|
11
|
+
'blank_line_after_opening_tag' => true,
|
12
|
+
'concat_space' => ['spacing' => 'one'],
|
13
|
+
'declare_strict_types' => true,
|
14
|
+
'increment_style' => ['style' => 'post'],
|
15
|
+
'is_null' => ['use_yoda_style' => false],
|
16
|
+
'list_syntax' => ['syntax' => 'short'],
|
17
|
+
'method_argument_space' => ['ensure_fully_multiline' => true],
|
18
|
+
'modernize_types_casting' => true,
|
19
|
+
'no_multiline_whitespace_before_semicolons' => true,
|
20
|
+
'no_useless_else' => true,
|
21
|
+
'no_useless_return' => true,
|
22
|
+
'ordered_imports' => true,
|
23
|
+
'phpdoc_align' => false,
|
24
|
+
'phpdoc_order' => true,
|
25
|
+
'php_unit_construct' => true,
|
26
|
+
'php_unit_dedicate_assert' => true,
|
27
|
+
'single_line_comment_style' => true,
|
28
|
+
'ternary_to_null_coalescing' => true,
|
29
|
+
'yoda_style' => false,
|
30
|
+
'void_return' => true,
|
31
|
+
])
|
32
|
+
->setFinder($finder)
|
33
|
+
->setUsingCache(true)
|
34
|
+
->setRiskyAllowed(true);
|
data/helpers/setup.sh
ADDED
@@ -0,0 +1,4 @@
|
|
1
|
+
php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');"
|
2
|
+
php -r "if (hash_file('SHA384', 'composer-setup.php') === '544e09ee996cdf60ece3804abc52599c22b1f40f4323403c44d44fdfdd586475ca9813a858088ffbc1f233e9b180f061') { echo 'Installer verified'; } else { echo hash_file('SHA384', 'composer-setup.php'); unlink('composer-setup.php'); } echo PHP_EOL;"
|
3
|
+
php composer-setup.php
|
4
|
+
php -r "unlink('composer-setup.php');"
|
@@ -0,0 +1,61 @@
|
|
1
|
+
<?php
|
2
|
+
|
3
|
+
declare(strict_types=1);
|
4
|
+
|
5
|
+
namespace Dependabot\PHP;
|
6
|
+
|
7
|
+
use Composer\DependencyResolver\Operation\InstallOperation;
|
8
|
+
use Composer\DependencyResolver\Operation\UninstallOperation;
|
9
|
+
use Composer\DependencyResolver\Operation\UpdateOperation;
|
10
|
+
use Composer\Installer\InstallationManager;
|
11
|
+
use Composer\Package\PackageInterface;
|
12
|
+
use Composer\Repository\RepositoryInterface;
|
13
|
+
|
14
|
+
class DependabotInstallationManager extends InstallationManager
|
15
|
+
{
|
16
|
+
private $installed = [];
|
17
|
+
private $updated = [];
|
18
|
+
private $uninstalled = [];
|
19
|
+
|
20
|
+
public function install(RepositoryInterface $repo, InstallOperation $operation): void
|
21
|
+
{
|
22
|
+
parent::install($repo, $operation);
|
23
|
+
$this->installed[] = $operation->getPackage();
|
24
|
+
}
|
25
|
+
|
26
|
+
public function update(RepositoryInterface $repo, UpdateOperation $operation): void
|
27
|
+
{
|
28
|
+
parent::update($repo, $operation);
|
29
|
+
$this->updated[] = [$operation->getInitialPackage(), $operation->getTargetPackage()];
|
30
|
+
}
|
31
|
+
|
32
|
+
public function uninstall(RepositoryInterface $repo, UninstallOperation $operation): void
|
33
|
+
{
|
34
|
+
parent::uninstall($repo, $operation);
|
35
|
+
$this->uninstalled[] = $operation->getPackage();
|
36
|
+
}
|
37
|
+
|
38
|
+
/**
|
39
|
+
* @return PackageInterface[]
|
40
|
+
*/
|
41
|
+
public function getInstalledPackages(): array
|
42
|
+
{
|
43
|
+
return $this->installed;
|
44
|
+
}
|
45
|
+
|
46
|
+
/**
|
47
|
+
* @return PackageInterface[]
|
48
|
+
*/
|
49
|
+
public function getUpdatedPackages(): array
|
50
|
+
{
|
51
|
+
return $this->updated;
|
52
|
+
}
|
53
|
+
|
54
|
+
/**
|
55
|
+
* @return PackageInterface[]
|
56
|
+
*/
|
57
|
+
public function getUninstalledPackages(): array
|
58
|
+
{
|
59
|
+
return $this->uninstalled;
|
60
|
+
}
|
61
|
+
}
|
@@ -0,0 +1,23 @@
|
|
1
|
+
<?php
|
2
|
+
|
3
|
+
declare(strict_types=1);
|
4
|
+
|
5
|
+
namespace Dependabot\PHP;
|
6
|
+
|
7
|
+
use Composer\Package\PackageInterface;
|
8
|
+
use Composer\Plugin\PluginManager;
|
9
|
+
|
10
|
+
class DependabotPluginManager extends PluginManager
|
11
|
+
{
|
12
|
+
public function registerPackage(PackageInterface $package, $failOnMissingClasses = false): void
|
13
|
+
{
|
14
|
+
// This package does some setup for PHP_CodeSniffer, but errors out the
|
15
|
+
// install if Symfony isn't installed (which it won't be for a lockfile
|
16
|
+
// only install run). Safe to ignore
|
17
|
+
if (strpos($package->getName(), 'phpcodesniffer') !== false) {
|
18
|
+
return;
|
19
|
+
}
|
20
|
+
|
21
|
+
parent::registerPackage($package, $failOnMissingClasses);
|
22
|
+
}
|
23
|
+
}
|
@@ -0,0 +1,25 @@
|
|
1
|
+
<?php
|
2
|
+
|
3
|
+
declare(strict_types=1);
|
4
|
+
|
5
|
+
namespace Dependabot\PHP;
|
6
|
+
|
7
|
+
use Composer\IO\NullIO;
|
8
|
+
|
9
|
+
class ExceptionIO extends NullIO
|
10
|
+
{
|
11
|
+
private $raise_next_error = false;
|
12
|
+
|
13
|
+
public function writeError($messages, $newline = true, $verbosity = self::NORMAL): void
|
14
|
+
{
|
15
|
+
if (is_array($messages)) {
|
16
|
+
return;
|
17
|
+
}
|
18
|
+
if ($this->raise_next_error) {
|
19
|
+
throw new \RuntimeException('Your requirements could not be resolved to an installable set of packages.' . $messages);
|
20
|
+
}
|
21
|
+
if (strpos($messages, 'Your requirements could not be resolved') !== false) {
|
22
|
+
$this->raise_next_error = true;
|
23
|
+
}
|
24
|
+
}
|
25
|
+
}
|
@@ -0,0 +1,21 @@
|
|
1
|
+
<?php
|
2
|
+
|
3
|
+
declare(strict_types=1);
|
4
|
+
|
5
|
+
namespace Dependabot\PHP;
|
6
|
+
|
7
|
+
use Composer\Factory;
|
8
|
+
|
9
|
+
class Hasher
|
10
|
+
{
|
11
|
+
public static function getContentHash(array $args): ?string
|
12
|
+
{
|
13
|
+
[$workingDirectory] = $args;
|
14
|
+
|
15
|
+
$io = new ExceptionIO();
|
16
|
+
$composer = Factory::create($io, $workingDirectory . '/composer.json');
|
17
|
+
$locker = $composer->getLocker();
|
18
|
+
|
19
|
+
return $locker->getContentHash(file_get_contents(Factory::getComposerFile()));
|
20
|
+
}
|
21
|
+
}
|
@@ -0,0 +1,123 @@
|
|
1
|
+
<?php
|
2
|
+
|
3
|
+
declare(strict_types=1);
|
4
|
+
|
5
|
+
namespace Dependabot\PHP;
|
6
|
+
|
7
|
+
use Composer\Factory;
|
8
|
+
use Composer\Installer;
|
9
|
+
use Composer\Package\PackageInterface;
|
10
|
+
|
11
|
+
class UpdateChecker
|
12
|
+
{
|
13
|
+
public static function getLatestResolvableVersion(array $args): ?string
|
14
|
+
{
|
15
|
+
[$workingDirectory, $dependencyName, $gitCredentials, $registryCredentials] = $args;
|
16
|
+
|
17
|
+
$io = new ExceptionIO();
|
18
|
+
$composer = Factory::create($io, $workingDirectory . '/composer.json');
|
19
|
+
$config = $composer->getConfig();
|
20
|
+
$httpBasicCredentials = [];
|
21
|
+
|
22
|
+
foreach ($gitCredentials as &$cred) {
|
23
|
+
$httpBasicCredentials[$cred['host']] = [
|
24
|
+
'username' => $cred['username'],
|
25
|
+
'password' => $cred['password'],
|
26
|
+
];
|
27
|
+
}
|
28
|
+
|
29
|
+
foreach ($registryCredentials as &$cred) {
|
30
|
+
$httpBasicCredentials[$cred['registry']] = [
|
31
|
+
'username' => $cred['username'],
|
32
|
+
'password' => $cred['password'],
|
33
|
+
];
|
34
|
+
}
|
35
|
+
|
36
|
+
if ($httpBasicCredentials) {
|
37
|
+
$config->merge(
|
38
|
+
[
|
39
|
+
'config' => [
|
40
|
+
'http-basic' => $httpBasicCredentials,
|
41
|
+
],
|
42
|
+
]
|
43
|
+
);
|
44
|
+
$io->loadConfiguration($config);
|
45
|
+
}
|
46
|
+
|
47
|
+
$installationManager = new DependabotInstallationManager();
|
48
|
+
$install = new Installer(
|
49
|
+
$io,
|
50
|
+
$config,
|
51
|
+
$composer->getPackage(),
|
52
|
+
$composer->getDownloadManager(),
|
53
|
+
$composer->getRepositoryManager(),
|
54
|
+
$composer->getLocker(),
|
55
|
+
$installationManager,
|
56
|
+
$composer->getEventDispatcher(),
|
57
|
+
$composer->getAutoloadGenerator()
|
58
|
+
);
|
59
|
+
|
60
|
+
// For all potential options, see UpdateCommand in composer
|
61
|
+
$install
|
62
|
+
->setDryRun(true)
|
63
|
+
->setUpdate(true)
|
64
|
+
->setDevMode(true)
|
65
|
+
->setUpdateWhitelist([$dependencyName])
|
66
|
+
->setWhitelistTransitiveDependencies(true)
|
67
|
+
->setExecuteOperations(false)
|
68
|
+
->setDumpAutoloader(false)
|
69
|
+
->setRunScripts(false);
|
70
|
+
|
71
|
+
/*
|
72
|
+
* If a platform is set we assume people know what they are doing and we respect the setting.
|
73
|
+
* If no platform is set we ignore it so that the php we run as doesn't interfere
|
74
|
+
*/
|
75
|
+
if ($config->get('platform') === []) {
|
76
|
+
$install->setIgnorePlatformRequirements(true);
|
77
|
+
}
|
78
|
+
|
79
|
+
$install->run();
|
80
|
+
|
81
|
+
$installedPackages = $installationManager->getInstalledPackages();
|
82
|
+
|
83
|
+
$updatedPackage = current(array_filter($installedPackages, function (PackageInterface $package) use ($dependencyName) {
|
84
|
+
return $package->getName() == $dependencyName;
|
85
|
+
}));
|
86
|
+
|
87
|
+
// We found the package in the list of updated packages. Return its version.
|
88
|
+
if ($updatedPackage) {
|
89
|
+
return preg_replace('/^([v])/', '', $updatedPackage->getPrettyVersion());
|
90
|
+
}
|
91
|
+
|
92
|
+
// We didn't find the package in the list of updated packages. Check if
|
93
|
+
// it was replaced by another package (in which case we can ignore).
|
94
|
+
foreach ($composer->getPackage()->getReplaces() as $link) {
|
95
|
+
if ($link->getTarget() == $dependencyName) {
|
96
|
+
return null;
|
97
|
+
}
|
98
|
+
}
|
99
|
+
foreach ($installedPackages as $package) {
|
100
|
+
foreach ($package->getReplaces() as $link) {
|
101
|
+
if ($link->getTarget() == $dependencyName) {
|
102
|
+
return null;
|
103
|
+
}
|
104
|
+
}
|
105
|
+
}
|
106
|
+
|
107
|
+
// Similarly, check if the package was provided by any other package.
|
108
|
+
foreach ($composer->getPackage()->getProvides() as $link) {
|
109
|
+
if ($link->getTarget() == $dependencyName) {
|
110
|
+
return preg_replace('/^([v])/', '', $link->getPrettyConstraint());
|
111
|
+
}
|
112
|
+
}
|
113
|
+
foreach ($installedPackages as $package) {
|
114
|
+
foreach ($package->getProvides() as $link) {
|
115
|
+
if ($link->getTarget() == $dependencyName) {
|
116
|
+
return preg_replace('/^([v])/', '', $link->getPrettyConstraint());
|
117
|
+
}
|
118
|
+
}
|
119
|
+
}
|
120
|
+
|
121
|
+
throw new \RuntimeException('Package not found in updated packages!');
|
122
|
+
}
|
123
|
+
}
|
@@ -0,0 +1,97 @@
|
|
1
|
+
<?php
|
2
|
+
|
3
|
+
declare(strict_types=1);
|
4
|
+
|
5
|
+
namespace Dependabot\PHP;
|
6
|
+
|
7
|
+
use Composer\Factory;
|
8
|
+
use Composer\Installer;
|
9
|
+
|
10
|
+
class Updater
|
11
|
+
{
|
12
|
+
public static function update(array $args): array
|
13
|
+
{
|
14
|
+
[$workingDirectory, $dependencyName, $dependencyVersion, $gitCredentials, $registryCredentials] = $args;
|
15
|
+
|
16
|
+
// Change working directory to the one provided, this ensures that we
|
17
|
+
// install dependencies into the working dir, rather than a vendor folder
|
18
|
+
// in the root of the project
|
19
|
+
$originalDir = getcwd();
|
20
|
+
chdir($workingDirectory);
|
21
|
+
|
22
|
+
$io = new ExceptionIO();
|
23
|
+
$composer = Factory::create($io);
|
24
|
+
$config = $composer->getConfig();
|
25
|
+
$httpBasicCredentials = [];
|
26
|
+
|
27
|
+
$pm = new DependabotPluginManager($io, $composer, null, false);
|
28
|
+
$composer->setPluginManager($pm);
|
29
|
+
$pm->loadInstalledPlugins();
|
30
|
+
|
31
|
+
foreach ($gitCredentials as &$cred) {
|
32
|
+
$httpBasicCredentials[$cred['host']] = [
|
33
|
+
'username' => $cred['username'],
|
34
|
+
'password' => $cred['password'],
|
35
|
+
];
|
36
|
+
}
|
37
|
+
|
38
|
+
foreach ($registryCredentials as &$cred) {
|
39
|
+
$httpBasicCredentials[$cred['registry']] = [
|
40
|
+
'username' => $cred['username'],
|
41
|
+
'password' => $cred['password'],
|
42
|
+
];
|
43
|
+
}
|
44
|
+
|
45
|
+
if ($httpBasicCredentials) {
|
46
|
+
$config->merge(
|
47
|
+
[
|
48
|
+
'config' => [
|
49
|
+
'http-basic' => $httpBasicCredentials,
|
50
|
+
],
|
51
|
+
]
|
52
|
+
);
|
53
|
+
$io->loadConfiguration($config);
|
54
|
+
}
|
55
|
+
|
56
|
+
$install = new Installer(
|
57
|
+
$io,
|
58
|
+
$config,
|
59
|
+
$composer->getPackage(),
|
60
|
+
$composer->getDownloadManager(),
|
61
|
+
$composer->getRepositoryManager(),
|
62
|
+
$composer->getLocker(),
|
63
|
+
$composer->getInstallationManager(),
|
64
|
+
$composer->getEventDispatcher(),
|
65
|
+
$composer->getAutoloadGenerator()
|
66
|
+
);
|
67
|
+
|
68
|
+
// For all potential options, see UpdateCommand in composer
|
69
|
+
$install
|
70
|
+
->setWriteLock(true)
|
71
|
+
->setUpdate(true)
|
72
|
+
->setDevMode(true)
|
73
|
+
->setUpdateWhitelist([$dependencyName])
|
74
|
+
->setWhitelistTransitiveDependencies(true)
|
75
|
+
->setExecuteOperations(false)
|
76
|
+
->setDumpAutoloader(false)
|
77
|
+
->setRunScripts(false);
|
78
|
+
|
79
|
+
/*
|
80
|
+
* If a platform is set we assume people know what they are doing and we respect the setting.
|
81
|
+
* If no platform is set we ignore it so that the php we run as doesn't interfere
|
82
|
+
*/
|
83
|
+
if ($config->get('platform') === []) {
|
84
|
+
$install->setIgnorePlatformRequirements(true);
|
85
|
+
}
|
86
|
+
|
87
|
+
$install->run();
|
88
|
+
|
89
|
+
$result = [
|
90
|
+
'composer.lock' => file_get_contents('composer.lock'),
|
91
|
+
];
|
92
|
+
|
93
|
+
chdir($originalDir);
|
94
|
+
|
95
|
+
return $result;
|
96
|
+
}
|
97
|
+
}
|
@@ -0,0 +1,11 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# These all need to be required so the various classes can be registered in a
|
4
|
+
# lookup table of package manager names to concrete classes.
|
5
|
+
require "dependabot/composer/file_fetcher"
|
6
|
+
require "dependabot/composer/file_parser"
|
7
|
+
require "dependabot/composer/update_checker"
|
8
|
+
require "dependabot/composer/file_updater"
|
9
|
+
require "dependabot/composer/metadata_finder"
|
10
|
+
require "dependabot/composer/requirement"
|
11
|
+
require "dependabot/composer/version"
|
@@ -0,0 +1,132 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "dependabot/file_fetchers"
|
4
|
+
require "dependabot/file_fetchers/base"
|
5
|
+
|
6
|
+
module Dependabot
|
7
|
+
module Composer
|
8
|
+
class FileFetcher < Dependabot::FileFetchers::Base
|
9
|
+
def self.required_files_in?(filenames)
|
10
|
+
filenames.include?("composer.json")
|
11
|
+
end
|
12
|
+
|
13
|
+
def self.required_files_message
|
14
|
+
"Repo must contain a composer.json."
|
15
|
+
end
|
16
|
+
|
17
|
+
private
|
18
|
+
|
19
|
+
def fetch_files
|
20
|
+
fetched_files = []
|
21
|
+
fetched_files << composer_json
|
22
|
+
fetched_files << composer_lock if composer_lock
|
23
|
+
fetched_files << auth_json if auth_json
|
24
|
+
fetched_files += path_dependencies
|
25
|
+
fetched_files
|
26
|
+
end
|
27
|
+
|
28
|
+
def composer_json
|
29
|
+
@composer_json ||= fetch_file_from_host("composer.json")
|
30
|
+
end
|
31
|
+
|
32
|
+
def composer_lock
|
33
|
+
return @composer_lock if @composer_lock_lookup_attempted
|
34
|
+
|
35
|
+
@composer_lock_lookup_attempted = true
|
36
|
+
@composer_lock ||= fetch_file_if_present("composer.lock")
|
37
|
+
end
|
38
|
+
|
39
|
+
# Note: This is fetched but currently unused
|
40
|
+
def auth_json
|
41
|
+
@auth_json ||= fetch_file_if_present("auth.json")&.
|
42
|
+
tap { |f| f.support_file = true }
|
43
|
+
end
|
44
|
+
|
45
|
+
def path_dependencies
|
46
|
+
@path_dependencies ||=
|
47
|
+
begin
|
48
|
+
composer_json_files = []
|
49
|
+
unfetchable_deps = []
|
50
|
+
|
51
|
+
path_sources.each do |path|
|
52
|
+
directories = path.end_with?("*") ? expand_path(path) : [path]
|
53
|
+
|
54
|
+
directories.each do |dir|
|
55
|
+
file = File.join(dir, "composer.json")
|
56
|
+
|
57
|
+
begin
|
58
|
+
composer_json_files << fetch_file_with_root_fallback(file)
|
59
|
+
rescue Dependabot::DependencyFileNotFound
|
60
|
+
# Collected, but currently ignored
|
61
|
+
unfetchable_deps << file
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
# Mark the path dependencies as support files - we don't currently
|
67
|
+
# parse or update them.
|
68
|
+
composer_json_files.tap do |files|
|
69
|
+
files.each { |f| f.support_file = true }
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
def path_sources
|
75
|
+
@path_sources ||=
|
76
|
+
JSON.parse(composer_json.content).
|
77
|
+
fetch("repositories", []).
|
78
|
+
select { |details| details["type"] == "path" }.
|
79
|
+
map { |details| details["url"] }
|
80
|
+
rescue JSON::ParserError
|
81
|
+
raise Dependabot::DependencyFileNotParseable, composer_json.path
|
82
|
+
end
|
83
|
+
|
84
|
+
def expand_path(path)
|
85
|
+
repo_contents(dir: path.gsub(/\*$/, "")).
|
86
|
+
select { |file| file.type == "dir" }.
|
87
|
+
map { |f| path.gsub(/\*$/, f.name) }
|
88
|
+
rescue Octokit::NotFound, Gitlab::Error::NotFound
|
89
|
+
# If there's no lockfile, or if none of the dependencies are path
|
90
|
+
# dependencies, then we can ignore failures to find path deps
|
91
|
+
return [] unless composer_lock&.content&.include?('"path"')
|
92
|
+
|
93
|
+
# Otherwise, we don't know what to do. For now, just raise. If we see
|
94
|
+
# this in the wild we can make a call on the correct handling
|
95
|
+
raise if directory == "/"
|
96
|
+
|
97
|
+
# If the directory isn't found at the full path, try looking for it
|
98
|
+
# at the root of the repository.
|
99
|
+
depth = directory.gsub(%r{^/}, "").gsub(%r{/$}, "").split("/").count
|
100
|
+
dir = "../" * depth + path.gsub(/\*$/, "")
|
101
|
+
|
102
|
+
repo_contents(dir: dir).
|
103
|
+
select { |file| file.type == "dir" }.
|
104
|
+
map { |f| path.gsub(/\*$/, f.name) }
|
105
|
+
end
|
106
|
+
|
107
|
+
def fetch_file_with_root_fallback(filename, type: "file")
|
108
|
+
path = Pathname.new(File.join(directory, filename)).cleanpath.to_path
|
109
|
+
|
110
|
+
begin
|
111
|
+
fetch_file_from_host(filename, type: type)
|
112
|
+
rescue Dependabot::DependencyFileNotFound
|
113
|
+
# If the file isn't found at the full path, try looking for it
|
114
|
+
# without considering the directory (i.e., check if the path should
|
115
|
+
# have been relevative to the root of the repository).
|
116
|
+
cleaned_filename = Pathname.new(filename).cleanpath.to_path
|
117
|
+
|
118
|
+
DependencyFile.new(
|
119
|
+
name: cleaned_filename,
|
120
|
+
content: fetch_file_content(cleaned_filename),
|
121
|
+
directory: directory,
|
122
|
+
type: type
|
123
|
+
)
|
124
|
+
end
|
125
|
+
rescue Octokit::NotFound, Gitlab::Error::NotFound
|
126
|
+
raise Dependabot::DependencyFileNotFound, path
|
127
|
+
end
|
128
|
+
end
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
Dependabot::FileFetchers.register("composer", Dependabot::Composer::FileFetcher)
|