-
Notifications
You must be signed in to change notification settings - Fork 8
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
implement parsing human-readable names from URLs
Based off of commit 257b768 Upstream-PR: NixOS/nix#8678 Co-authored-by: Felix Uhl <[email protected]> Change-Id: Idcb7f6191ca3310ef9dc854197f7798260c3f71d
- Loading branch information
1 parent
e2ab89a
commit 1425aa0
Showing
7 changed files
with
157 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
#include <iostream> | ||
#include <regex> | ||
|
||
#include "url-name.hh" | ||
|
||
namespace nix { | ||
|
||
static std::string const attributeNamePattern("[a-z0-9_-]+"); | ||
static std::regex const lastAttributeRegex("(?:" + attributeNamePattern + "\\.)*(?!default)(" + attributeNamePattern +")(\\^.*)?"); | ||
static std::string const pathSegmentPattern("[a-zA-Z0-9_-]+"); | ||
static std::regex const lastPathSegmentRegex(".*/(" + pathSegmentPattern +")"); | ||
static std::regex const secondPathSegmentRegex("(?:" + pathSegmentPattern + ")/(" + pathSegmentPattern +")(?:/.*)?"); | ||
static std::regex const gitProviderRegex("github|gitlab|sourcehut"); | ||
static std::regex const gitSchemeRegex("git($|\\+.*)"); | ||
static std::regex const defaultOutputRegex(".*\\.default($|\\^.*)"); | ||
|
||
std::optional<std::string> getNameFromURL(ParsedURL const & url) | ||
{ | ||
std::smatch match; | ||
|
||
/* If there is a dir= argument, use its value */ | ||
if (url.query.count("dir") > 0) { | ||
return url.query.at("dir"); | ||
} | ||
|
||
/* If the fragment isn't a "default" and contains two attribute elements, use the last one */ | ||
if (std::regex_match(url.fragment, match, lastAttributeRegex)) { | ||
return match.str(1); | ||
} | ||
|
||
/* If this is a github/gitlab/sourcehut flake, use the repo name */ | ||
if ( | ||
std::regex_match(url.scheme, gitProviderRegex) | ||
&& std::regex_match(url.path, match, secondPathSegmentRegex) | ||
) { | ||
return match.str(1); | ||
} | ||
|
||
/* If it is a regular git flake, use the directory name */ | ||
if ( | ||
std::regex_match(url.scheme, gitSchemeRegex) | ||
&& std::regex_match(url.path, match, lastPathSegmentRegex) | ||
) { | ||
return match.str(1); | ||
} | ||
|
||
/* If everything failed but there is a non-default fragment, use it in full */ | ||
if (!url.fragment.empty() && !std::regex_match(url.fragment, defaultOutputRegex)) | ||
return url.fragment; | ||
|
||
/* If there is no fragment, take the last element of the path */ | ||
if (std::regex_match(url.path, match, lastPathSegmentRegex)) | ||
return match.str(1); | ||
|
||
/* If even that didn't work, the URL does not contain enough info to determine a useful name */ | ||
return {}; | ||
} | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
#pragma once | ||
///@file url-name.hh, for some hueristic-ish URL parsing. | ||
|
||
#include <string> | ||
#include <optional> | ||
|
||
#include "url.hh" | ||
#include "url-parts.hh" | ||
#include "util.hh" | ||
#include "split.hh" | ||
|
||
namespace nix { | ||
|
||
/** | ||
* Try to extract a reasonably unique and meaningful, human-readable | ||
* name of a flake output from a parsed URL. | ||
* When nullopt is returned, the callsite should use information available | ||
* to it outside of the URL to determine a useful name. | ||
* This is a heuristic approach intended for user interfaces. | ||
* @return nullopt if the extracted name is not useful to identify a | ||
* flake output, for example because it is empty or "default". | ||
* Otherwise returns the extracted name. | ||
*/ | ||
std::optional<std::string> getNameFromURL(ParsedURL const & url); | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,67 @@ | ||
#include "url-name.hh" | ||
#include <gtest/gtest.h> | ||
|
||
namespace nix { | ||
|
||
/* ----------- tests for url-name.hh --------------------------------------------------*/ | ||
|
||
TEST(getNameFromURL, getsNameFromURL) { | ||
ASSERT_EQ(getNameFromURL(parseURL("path:/home/user/project")), "project"); | ||
ASSERT_EQ(getNameFromURL(parseURL("path:~/repos/nixpkgs#packages.x86_64-linux.hello")), "hello"); | ||
ASSERT_EQ(getNameFromURL(parseURL("path:.#nonStandardAttr.mylaptop")), "nonStandardAttr.mylaptop"); | ||
ASSERT_EQ(getNameFromURL(parseURL("path:./repos/myflake#nonStandardAttr.mylaptop")), "nonStandardAttr.mylaptop"); | ||
ASSERT_EQ(getNameFromURL(parseURL("path:./nixpkgs#packages.x86_64-linux.complex^bin,man")), "complex"); | ||
ASSERT_EQ(getNameFromURL(parseURL("path:./myproj#packages.x86_64-linux.default^*")), "myproj"); | ||
|
||
ASSERT_EQ(getNameFromURL(parseURL("github:NixOS/nixpkgs#packages.x86_64-linux.hello")), "hello"); | ||
ASSERT_EQ(getNameFromURL(parseURL("github:NixOS/nixpkgs#hello")), "hello"); | ||
ASSERT_EQ(getNameFromURL(parseURL("github:NixOS/nix#packages.x86_64-linux.default")), "nix"); | ||
ASSERT_EQ(getNameFromURL(parseURL("github:NixOS/nix#")), "nix"); | ||
ASSERT_EQ(getNameFromURL(parseURL("github:NixOS/nix")), "nix"); | ||
ASSERT_EQ(getNameFromURL(parseURL("github:cachix/devenv/main#packages.x86_64-linux.default")), "devenv"); | ||
ASSERT_EQ(getNameFromURL(parseURL("github:edolstra/nix-warez?rev=1234&dir=blender&ref=master")), "blender"); | ||
|
||
ASSERT_EQ(getNameFromURL(parseURL("gitlab:NixOS/nixpkgs#packages.x86_64-linux.hello")), "hello"); | ||
ASSERT_EQ(getNameFromURL(parseURL("gitlab:NixOS/nixpkgs#hello")), "hello"); | ||
ASSERT_EQ(getNameFromURL(parseURL("gitlab:NixOS/nix#packages.x86_64-linux.default")), "nix"); | ||
ASSERT_EQ(getNameFromURL(parseURL("gitlab:NixOS/nix#")), "nix"); | ||
ASSERT_EQ(getNameFromURL(parseURL("gitlab:NixOS/nix")), "nix"); | ||
ASSERT_EQ(getNameFromURL(parseURL("gitlab:cachix/devenv/main#packages.x86_64-linux.default")), "devenv"); | ||
|
||
ASSERT_EQ(getNameFromURL(parseURL("sourcehut:NixOS/nixpkgs#packages.x86_64-linux.hello")), "hello"); | ||
ASSERT_EQ(getNameFromURL(parseURL("sourcehut:NixOS/nixpkgs#hello")), "hello"); | ||
ASSERT_EQ(getNameFromURL(parseURL("sourcehut:NixOS/nix#packages.x86_64-linux.default")), "nix"); | ||
ASSERT_EQ(getNameFromURL(parseURL("sourcehut:NixOS/nix#")), "nix"); | ||
ASSERT_EQ(getNameFromURL(parseURL("sourcehut:NixOS/nix")), "nix"); | ||
ASSERT_EQ(getNameFromURL(parseURL("sourcehut:cachix/devenv/main#packages.x86_64-linux.default")), "devenv"); | ||
|
||
ASSERT_EQ(getNameFromURL(parseURL("git://github.com/edolstra/dwarffs")), "dwarffs"); | ||
ASSERT_EQ(getNameFromURL(parseURL("git://github.com/edolstra/nix-warez?dir=blender")), "blender"); | ||
ASSERT_EQ(getNameFromURL(parseURL("git+file:///home/user/project")), "project"); | ||
ASSERT_EQ(getNameFromURL(parseURL("git+file:///home/user/project?ref=fa1e2d23a22")), "project"); | ||
ASSERT_EQ(getNameFromURL(parseURL("git+ssh://[email protected]/someuser/my-repo#")), "my-repo"); | ||
ASSERT_EQ(getNameFromURL(parseURL("git+git://github.com/someuser/my-repo?rev=v1.2.3")), "my-repo"); | ||
ASSERT_EQ(getNameFromURL(parseURL("git+ssh:///home/user/project?dir=subproject&rev=v2.4")), "subproject"); | ||
ASSERT_EQ(getNameFromURL(parseURL("git+http://not-even-real#packages.x86_64-linux.hello")), "hello"); | ||
ASSERT_EQ(getNameFromURL(parseURL("git+https://not-even-real#packages.aarch64-darwin.hello")), "hello"); | ||
|
||
ASSERT_EQ(getNameFromURL(parseURL("tarball+http://github.com/NixOS/nix/archive/refs/tags/2.18.1#packages.x86_64-linux.jq")), "jq"); | ||
ASSERT_EQ(getNameFromURL(parseURL("tarball+https://github.com/NixOS/nix/archive/refs/tags/2.18.1#packages.x86_64-linux.hg")), "hg"); | ||
ASSERT_EQ(getNameFromURL(parseURL("tarball+file:///home/user/Downloads/nixpkgs-2.18.1#packages.aarch64-darwin.ripgrep")), "ripgrep"); | ||
|
||
ASSERT_EQ(getNameFromURL(parseURL("https://github.com/NixOS/nix/archive/refs/tags/2.18.1.tar.gz#packages.x86_64-linux.pv")), "pv"); | ||
ASSERT_EQ(getNameFromURL(parseURL("http://github.com/NixOS/nix/archive/refs/tags/2.18.1.tar.gz#packages.x86_64-linux.pv")), "pv"); | ||
|
||
ASSERT_EQ(getNameFromURL(parseURL("file:///home/user/project?ref=fa1e2d23a22")), "project"); | ||
ASSERT_EQ(getNameFromURL(parseURL("file+file:///home/user/project?ref=fa1e2d23a22")), "project"); | ||
ASSERT_EQ(getNameFromURL(parseURL("file+http://not-even-real#packages.x86_64-linux.hello")), "hello"); | ||
ASSERT_EQ(getNameFromURL(parseURL("file+http://gitfantasy.com/org/user/notaflake")), "notaflake"); | ||
ASSERT_EQ(getNameFromURL(parseURL("file+https://not-even-real#packages.aarch64-darwin.hello")), "hello"); | ||
|
||
ASSERT_EQ(getNameFromURL(parseURL("https://www.github.com/")), std::nullopt); | ||
ASSERT_EQ(getNameFromURL(parseURL("path:.")), std::nullopt); | ||
ASSERT_EQ(getNameFromURL(parseURL("file:.#")), std::nullopt); | ||
ASSERT_EQ(getNameFromURL(parseURL("path:.#packages.x86_64-linux.default")), std::nullopt); | ||
ASSERT_EQ(getNameFromURL(parseURL("path:.#packages.x86_64-linux.default^*")), std::nullopt); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters