Skip to content

Commit

Permalink
Handle dependency names containing multiple @
Browse files Browse the repository at this point in the history
  • Loading branch information
jhatlak committed Jan 13, 2022
1 parent cda4cfc commit c634b3d
Show file tree
Hide file tree
Showing 2 changed files with 41 additions and 25 deletions.
51 changes: 26 additions & 25 deletions src/Parser.php
Original file line number Diff line number Diff line change
Expand Up @@ -75,8 +75,8 @@ public function parse($input, $assoc = false)
if ($line[0] === '#') {
continue;
}
if ($line[strlen($line) - 1] == ':') {
$indentationLevel += 1;
if ($line[strlen($line) - 1] === ':') {
++$indentationLevel;
$currentKey = substr($line, 0, -1);
$current->$currentKey = new \stdClass();
$current->$currentKey->__parent = $current;
Expand Down Expand Up @@ -138,10 +138,10 @@ protected static function parseValue($input)
return $input;
}

protected static function cleanupObject(&$object)
protected static function cleanupObject($object)
{
unset($object->__parent);
foreach (get_object_vars($object) as $key => $value) {
foreach (get_object_vars($object) as $value) {
if ($value instanceof \stdClass) {
self::cleanupObject($value);
}
Expand Down Expand Up @@ -177,16 +177,11 @@ public static function parseVersionStrings($key)
$currentKey = '';
$isString = false;
for ($i = 0; $i < strlen($key); $i++) {
if ($key[$i] == '"') {
if (!$isString) {
$isString = true;
continue;
} else {
$isString = false;
continue;
}
if ($key[$i] === '"') {
$isString = !$isString;
continue;
}
if (!$isString && $key[$i] == ',') {
if (!$isString && $key[$i] === ',') {
$result[] = $currentKey;
$currentKey = '';
continue;
Expand All @@ -197,24 +192,30 @@ public static function parseVersionStrings($key)
$result[] = $currentKey;
}
}
$result = array_map(function($e) { return trim($e); }, $result);
return $result;

return array_map('trim', $result);
}

/**
* To avoid splitting on scoped package-names, every but the last @ are considered
* package name.
*
* @param string $versionString
* @return string[]
*/
public static function splitVersionString($versionString)
{
$parts = explode('@', $versionString);
$version = array_pop($parts);
return [
implode('@', $parts),
$version
];
// Scoped package names start with an "@" → skip the first character.
// Note: $versionString may contain even more than two "@" if version is "protocol://user@host..."
$location = strpos($versionString, '@', 1);
if ($location > 0) {
$name = substr($versionString, 0, $location);
$version = substr($versionString, $location + 1);

// Handle special cases that package.json allows for "Git URLs as Dependencies"
if (preg_match('/#(semver:)?(.+)$/', $version, $matches)) {
$version = $matches[2];
}

return [$name, $version];
}
throw new \InvalidArgumentException('Version string is expected to contain "@" separating name from version.');
}
}
}
15 changes: 15 additions & 0 deletions tests/ParserTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -219,6 +219,21 @@ public function testVersionSplitting()
['@gulp-sourcemaps/identity-map', '1.X'],
Parser::splitVersionString('@gulp-sourcemaps/[email protected]')
);

$this->assertEquals(
['@foo/bar', '^1.2.3'],
Parser::splitVersionString('@foo/bar@git+ssh://user@host:1234/foo/bar#semver:^1.2.3')
);

$this->assertEquals(
['@foo/bar', 'v1.2.3'],
Parser::splitVersionString('@foo/bar@git://user@host/foo/bar.git#v1.2.3')
);

$this->assertEquals(
['@foo/bar', 'file:vendor/foo/bar'],
Parser::splitVersionString('@foo/bar@file:vendor/foo/bar')
);
}

/**
Expand Down

0 comments on commit c634b3d

Please sign in to comment.