From 3c1cd4a248970f85a596a092afe49cc3028050e9 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 3 Jan 2025 07:15:59 -0800 Subject: [PATCH 1/5] chore: bump @npmcli/template-oss from 4.23.4 to 4.23.5 (#285) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [@npmcli/template-oss](https://github.com/npm/template-oss) from 4.23.4 to 4.23.5.
Release notes

Sourced from @​npmcli/template-oss's releases.

v4.23.5

4.23.5 (2024-11-25)

Bug Fixes

Dependencies

Chores

Changelog

Sourced from @​npmcli/template-oss's changelog.

4.23.5 (2024-11-25)

Bug Fixes

Dependencies

Chores

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=@npmcli/template-oss&package-manager=npm_and_yarn&previous-version=4.23.4&new-version=4.23.5)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) You can trigger a rebase of this PR by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
> **Note** > Automatic rebases have been disabled on this pull request as it has been open for over 30 days. --------- Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: npm CLI robot --- package.json | 4 ++-- release-please-config.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/package.json b/package.json index 7835615..a97c687 100644 --- a/package.json +++ b/package.json @@ -35,7 +35,7 @@ }, "devDependencies": { "@npmcli/eslint-config": "^5.0.0", - "@npmcli/template-oss": "4.23.4", + "@npmcli/template-oss": "4.23.5", "tap": "^16.0.1" }, "files": [ @@ -55,7 +55,7 @@ }, "templateOSS": { "//@npmcli/template-oss": "This file is partially managed by @npmcli/template-oss. Edits may be overwritten.", - "version": "4.23.4", + "version": "4.23.5", "publish": "true" } } diff --git a/release-please-config.json b/release-please-config.json index a1676b9..c56fd1d 100644 --- a/release-please-config.json +++ b/release-please-config.json @@ -33,5 +33,5 @@ "package-name": "" } }, - "prerelease-type": "pre" + "prerelease-type": "pre.0" } From 80131c308c6b6fcf6799a1a512c997ee3ad6e669 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 9 Apr 2025 08:41:00 -0700 Subject: [PATCH 2/5] chore: bump @npmcli/template-oss from 4.23.5 to 4.23.6 (#290) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [@npmcli/template-oss](https://github.com/npm/template-oss) from 4.23.5 to 4.23.6.
Release notes

Sourced from @​npmcli/template-oss's releases.

v4.23.6

4.23.6 (2024-12-11)

Bug Fixes

Changelog

Sourced from @​npmcli/template-oss's changelog.

4.23.6 (2024-12-11)

Bug Fixes

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=@npmcli/template-oss&package-manager=npm_and_yarn&previous-version=4.23.5&new-version=4.23.6)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) You can trigger a rebase of this PR by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
> **Note** > Automatic rebases have been disabled on this pull request as it has been open for over 30 days. --------- Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: npm CLI robot --- package.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index a97c687..d070d9a 100644 --- a/package.json +++ b/package.json @@ -35,7 +35,7 @@ }, "devDependencies": { "@npmcli/eslint-config": "^5.0.0", - "@npmcli/template-oss": "4.23.5", + "@npmcli/template-oss": "4.23.6", "tap": "^16.0.1" }, "files": [ @@ -55,7 +55,7 @@ }, "templateOSS": { "//@npmcli/template-oss": "This file is partially managed by @npmcli/template-oss. Edits may be overwritten.", - "version": "4.23.5", + "version": "4.23.6", "publish": "true" } } From ac08fe89153d19d1fecbd1e5ce5014fad833134c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 10 Apr 2025 06:54:54 -0700 Subject: [PATCH 3/5] chore: bump @npmcli/template-oss from 4.23.6 to 4.24.3 (#296) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [@npmcli/template-oss](https://github.com/npm/template-oss) from 4.23.6 to 4.24.3.
Release notes

Sourced from @​npmcli/template-oss's releases.

v4.24.3

4.24.3 (2025-03-31)

Bug Fixes

v4.24.2

4.24.2 (2025-03-05)

Bug Fixes

v4.24.1

4.24.1 (2025-02-04)

Bug Fixes

v4.24.0

4.24.0 (2025-01-30)

Features

Dependencies

Changelog

Sourced from @​npmcli/template-oss's changelog.

4.24.3 (2025-03-31)

Bug Fixes

4.24.2 (2025-03-05)

Bug Fixes

4.24.1 (2025-02-04)

Bug Fixes

4.24.0 (2025-01-30)

Features

Dependencies

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=@npmcli/template-oss&package-manager=npm_and_yarn&previous-version=4.23.6&new-version=4.24.3)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
--------- Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: npm CLI robot --- .gitignore | 1 + package.json | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/.gitignore b/.gitignore index 2bab6d1..dedbc77 100644 --- a/.gitignore +++ b/.gitignore @@ -5,6 +5,7 @@ !**/.gitignore !/.commitlintrc.js +!/.eslint.config.js !/.eslintrc.js !/.eslintrc.local.* !/.git-blame-ignore-revs diff --git a/package.json b/package.json index d070d9a..ad9357f 100644 --- a/package.json +++ b/package.json @@ -35,7 +35,7 @@ }, "devDependencies": { "@npmcli/eslint-config": "^5.0.0", - "@npmcli/template-oss": "4.23.6", + "@npmcli/template-oss": "4.24.3", "tap": "^16.0.1" }, "files": [ @@ -55,7 +55,7 @@ }, "templateOSS": { "//@npmcli/template-oss": "This file is partially managed by @npmcli/template-oss. Edits may be overwritten.", - "version": "4.23.6", + "version": "4.24.3", "publish": "true" } } From ef0865cc5c28700f990bf25d919e2520c944cf55 Mon Sep 17 00:00:00 2001 From: Jordan Harband Date: Mon, 14 Apr 2025 10:35:15 -0700 Subject: [PATCH 4/5] feat: add `HostedGitInfo.fromManifest` (#288) This encapsulates the logic used in `npm repo` Per Slack discussion. Once this is published and updated in the cli, I'll happily adapt the `npm repo` code to use this method. The method will either return a HGI instance, a string URL, or `null`. --- README.md | 7 ++++- lib/index.js | 48 +++++++++++++++++++++++++++++++ test/file.js | 14 +++++++++ test/github.js | 77 ++++++++++++++++++++++++++++++++++++++++++++++++++ test/gitlab.js | 77 ++++++++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 222 insertions(+), 1 deletion(-) create mode 100644 test/file.js diff --git a/README.md b/README.md index 498e3d2..c5a537e 100644 --- a/README.md +++ b/README.md @@ -19,7 +19,7 @@ const info = hostedGitInfo.fromUrl("git@github.com:npm/hosted-git-info.git", opt */ ``` -If the URL can't be matched with a git host, `null` will be returned. We +If the URL can't be matched with a git host, `null` will be returned. We can match git, ssh and https urls. Additionally, we can match ssh connect strings (`git@github.com:npm/hosted-git-info`) and shortcuts (eg, `github:npm/hosted-git-info`). GitHub specifically, is detected in the case @@ -59,6 +59,11 @@ Implications: * *noCommittish* — If true then committishes won't be included in generated URLs. * *noGitPlus* — If true then `git+` won't be prefixed on URLs. +### const infoOrURL = hostedGitInfo.fromManifest(manifest[, options]) + +* *manifest* is a package manifest, such as that returned by [`pacote.manifest()`](https://npmjs.com/pacote) +* *options* is an optional object. It can have the same properties as `fromUrl` above. + ## Methods All of the methods take the same options as the `fromUrl` factory. Options diff --git a/lib/index.js b/lib/index.js index 0c9d0b0..2a7100d 100644 --- a/lib/index.js +++ b/lib/index.js @@ -7,6 +7,26 @@ const parseUrl = require('./parse-url.js') const cache = new LRUCache({ max: 1000 }) +function unknownHostedUrl (url) { + try { + const { + protocol, + hostname, + pathname, + } = new URL(url) + + if (!hostname) { + return null + } + + const proto = /(?:git\+)http:$/.test(protocol) ? 'http:' : 'https:' + const path = pathname.replace(/\.git$/, '') + return `${proto}//${hostname}${path}` + } catch { + return null + } +} + class GitHost { constructor (type, user, auth, project, committish, defaultRepresentation, opts = {}) { Object.assign(this, GitHost.#gitHosts[type], { @@ -56,6 +76,34 @@ class GitHost { return cache.get(key) } + static fromManifest (manifest, opts = {}) { + if (!manifest || typeof manifest !== 'object') { + return + } + + const r = manifest.repository + // TODO: look into also checking the `bugs`/`homepage` URLs + + const rurl = r && ( + typeof r === 'string' + ? r + : typeof r === 'object' && typeof r.url === 'string' + ? r.url + : null + ) + + if (!rurl) { + throw new Error('no repository') + } + + const info = (rurl && GitHost.fromUrl(rurl.replace(/^git\+/, ''), opts)) || null + if (info) { + return info + } + const unk = unknownHostedUrl(rurl) + return GitHost.fromUrl(unk, opts) || unk + } + static parseUrl (url) { return parseUrl(url) } diff --git a/test/file.js b/test/file.js new file mode 100644 index 0000000..2cd2de0 --- /dev/null +++ b/test/file.js @@ -0,0 +1,14 @@ +const HostedGit = require('..') +const t = require('tap') + +t.test('file:// URLs', t => { + const fileRepo = { + name: 'foo', + repository: { + url: 'file:///path/dot.git', + }, + } + t.equal(HostedGit.fromManifest(fileRepo), null) + + t.end() +}) diff --git a/test/github.js b/test/github.js index 6c01068..7d7739b 100644 --- a/test/github.js +++ b/test/github.js @@ -270,3 +270,80 @@ t.test('string methods populate correctly', t => { t.end() }) + +t.test('from manifest', t => { + t.equal(HostedGit.fromManifest(), undefined, 'no manifest returns undefined') + t.equal(HostedGit.fromManifest(), undefined, 'no manifest returns undefined') + t.equal(HostedGit.fromManifest(false), undefined, 'false manifest returns undefined') + t.equal(HostedGit.fromManifest(() => {}), undefined, 'function manifest returns undefined') + + const unknownHostRepo = { + name: 'foo', + repository: { + url: 'https://nope.com', + }, + } + t.same(HostedGit.fromManifest(unknownHostRepo), 'https://nope.com/') + + const insecureUnknownHostRepo = { + name: 'foo', + repository: { + url: 'http://nope.com', + }, + } + t.same(HostedGit.fromManifest(insecureUnknownHostRepo), 'https://nope.com/') + + const insecureGitUnknownHostRepo = { + name: 'foo', + repository: { + url: 'git+http://nope.com', + }, + } + t.same(HostedGit.fromManifest(insecureGitUnknownHostRepo), 'http://nope.com') + + const badRepo = { + name: 'foo', + repository: { + url: '#', + }, + } + t.equal(HostedGit.fromManifest(badRepo), null) + + const manifest = { + name: 'foo', + repository: { + type: 'git', + url: 'git+ssh://github.com/foo/bar.git', + }, + } + + const parsed = HostedGit.fromManifest(manifest) + t.same(parsed.browse(), 'https://github.com/foo/bar') + + const monorepo = { + name: 'clowncar', + repository: { + type: 'git', + url: 'git+ssh://github.com/foo/bar.git', + directory: 'packages/foo', + }, + } + + const honk = HostedGit.fromManifest(monorepo) + t.same(honk.browse(monorepo.repository.directory), 'https://github.com/foo/bar/tree/HEAD/packages/foo') + + const stringRepo = { + name: 'foo', + repository: 'git+ssh://github.com/foo/bar.git', + } + const stringRepoParsed = HostedGit.fromManifest(stringRepo) + t.same(stringRepoParsed.browse(), 'https://github.com/foo/bar') + + const nonStringRepo = { + name: 'foo', + repository: 42, + } + t.throws(() => HostedGit.fromManifest(nonStringRepo)) + + t.end() +}) diff --git a/test/gitlab.js b/test/gitlab.js index 685bd06..ffa080c 100644 --- a/test/gitlab.js +++ b/test/gitlab.js @@ -321,3 +321,80 @@ t.test('string methods populate correctly', t => { t.end() }) + +t.test('from manifest', t => { + t.equal(HostedGit.fromManifest(), undefined, 'no manifest returns undefined') + t.equal(HostedGit.fromManifest(), undefined, 'no manifest returns undefined') + t.equal(HostedGit.fromManifest(false), undefined, 'false manifest returns undefined') + t.equal(HostedGit.fromManifest(() => {}), undefined, 'function manifest returns undefined') + + const unknownHostRepo = { + name: 'foo', + repository: { + url: 'https://nope.com', + }, + } + t.same(HostedGit.fromManifest(unknownHostRepo), 'https://nope.com/') + + const insecureUnknownHostRepo = { + name: 'foo', + repository: { + url: 'http://nope.com', + }, + } + t.same(HostedGit.fromManifest(insecureUnknownHostRepo), 'https://nope.com/') + + const insecureGitUnknownHostRepo = { + name: 'foo', + repository: { + url: 'git+http://nope.com', + }, + } + t.same(HostedGit.fromManifest(insecureGitUnknownHostRepo), 'http://nope.com') + + const badRepo = { + name: 'foo', + repository: { + url: '#', + }, + } + t.equal(HostedGit.fromManifest(badRepo), null) + + const manifest = { + name: 'foo', + repository: { + type: 'git', + url: 'git+ssh://gitlab.com/foo/bar.git', + }, + } + + const parsed = HostedGit.fromManifest(manifest) + t.same(parsed.browse(), 'https://gitlab.com/foo/bar') + + const monorepo = { + name: 'clowncar', + repository: { + type: 'git', + url: 'git+ssh://gitlab.com/foo/bar.git', + directory: 'packages/foo', + }, + } + + const honk = HostedGit.fromManifest(monorepo) + t.same(honk.browse(monorepo.repository.directory), 'https://gitlab.com/foo/bar/tree/HEAD/packages/foo') + + const stringRepo = { + name: 'foo', + repository: 'git+ssh://gitlab.com/foo/bar.git', + } + const stringRepoParsed = HostedGit.fromManifest(stringRepo) + t.same(stringRepoParsed.browse(), 'https://gitlab.com/foo/bar') + + const nonStringRepo = { + name: 'foo', + repository: 42, + } + t.throws(() => HostedGit.fromManifest(nonStringRepo)) + + t.end() +}) From 3dfd77128d9ecabf9ef692ca5af17c9349c56a4e Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Mon, 14 Apr 2025 11:29:05 -0700 Subject: [PATCH 5/5] chore: release 8.1.0 (#297) :robot: I have created a release *beep* *boop* --- ## [8.1.0](https://github.com/npm/hosted-git-info/compare/v8.0.2...v8.1.0) (2025-04-14) ### Features * [`ef0865c`](https://github.com/npm/hosted-git-info/commit/ef0865cc5c28700f990bf25d919e2520c944cf55) [#288](https://github.com/npm/hosted-git-info/pull/288) add `HostedGitInfo.fromManifest` (#288) (@ljharb) ### Chores * [`ac08fe8`](https://github.com/npm/hosted-git-info/commit/ac08fe89153d19d1fecbd1e5ce5014fad833134c) [#296](https://github.com/npm/hosted-git-info/pull/296) bump @npmcli/template-oss from 4.23.6 to 4.24.3 (#296) (@dependabot[bot], @npm-cli-bot) --- This PR was generated with [Release Please](https://github.com/googleapis/release-please). See [documentation](https://github.com/googleapis/release-please#release-please). Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> --- .release-please-manifest.json | 2 +- CHANGELOG.md | 6 ++++++ package.json | 2 +- 3 files changed, 8 insertions(+), 2 deletions(-) diff --git a/.release-please-manifest.json b/.release-please-manifest.json index 6331e90..529b133 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "8.0.2" + ".": "8.1.0" } diff --git a/CHANGELOG.md b/CHANGELOG.md index ea84dac..f2a1030 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,11 @@ # Changelog +## [8.1.0](https://github.com/npm/hosted-git-info/compare/v8.0.2...v8.1.0) (2025-04-14) +### Features +* [`ef0865c`](https://github.com/npm/hosted-git-info/commit/ef0865cc5c28700f990bf25d919e2520c944cf55) [#288](https://github.com/npm/hosted-git-info/pull/288) add `HostedGitInfo.fromManifest` (#288) (@ljharb) +### Chores +* [`ac08fe8`](https://github.com/npm/hosted-git-info/commit/ac08fe89153d19d1fecbd1e5ce5014fad833134c) [#296](https://github.com/npm/hosted-git-info/pull/296) bump @npmcli/template-oss from 4.23.6 to 4.24.3 (#296) (@dependabot[bot], @npm-cli-bot) + ## [8.0.2](https://github.com/npm/hosted-git-info/compare/v8.0.1...v8.0.2) (2024-11-21) ### Bug Fixes * [`cc004ba`](https://github.com/npm/hosted-git-info/commit/cc004bae62d17b90c2fc889fcde5afbcac2fc508) [#280](https://github.com/npm/hosted-git-info/pull/280) even better regex for host fragment (#280) (@wraithgar) diff --git a/package.json b/package.json index ad9357f..a9bb26b 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "hosted-git-info", - "version": "8.0.2", + "version": "8.1.0", "description": "Provides metadata and conversions from repository urls for GitHub, Bitbucket and GitLab", "main": "./lib/index.js", "repository": {