git-find-remote 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +36 -0
- package/bin/cli.js +12 -0
- package/git-find-remote-1.0.0.tgz +0 -0
- package/lib/git.js +54 -0
- package/lib/matches.js +26 -0
- package/lib/normalize.js +45 -0
- package/lib/search.js +68 -0
- package/package.json +32 -0
package/README.md
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
# git-find-remote
|
|
2
|
+
|
|
3
|
+
A CLI tool that recursively searches directories and finds Git repositories by remote URL or repository name. Have you ever worked on a project and forgot with you had been working on it on your computer? This is the package for you. It will locate the package on your computer.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install -g git-find-remote
|
|
9
|
+
```
|
|
10
|
+
Or if you dont want to install you can use:
|
|
11
|
+
```bash
|
|
12
|
+
npx git-find-remote your-github-repo-name
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
## Usage
|
|
16
|
+
|
|
17
|
+
You can search for your repos in 3 ways.
|
|
18
|
+
1. Using just the repository name:
|
|
19
|
+
```bash
|
|
20
|
+
git-find-remote your-github-repo-name
|
|
21
|
+
```
|
|
22
|
+
2. Including the username for the repository
|
|
23
|
+
```bash
|
|
24
|
+
git-find-remote your-username/your-github-repo-name
|
|
25
|
+
```
|
|
26
|
+
3. Full Github url
|
|
27
|
+
```bash
|
|
28
|
+
git-find-remote https://github.com/your-username/your-github-repo-name
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
## Features
|
|
32
|
+
- Recursive directory search
|
|
33
|
+
- Supports HTTPS Git URLs
|
|
34
|
+
- Supports SSH Git URLs
|
|
35
|
+
- Search by repository name
|
|
36
|
+
- Ignores node_modules and build folders
|
package/bin/cli.js
ADDED
|
Binary file
|
package/lib/git.js
ADDED
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
const fs = require("fs/promises")
|
|
2
|
+
const path = require("path")
|
|
3
|
+
const { execFile } = require("child_process")
|
|
4
|
+
const { promisify } = require("util")
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
const execFileAsync = promisify(execFile)
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
async function getRemote(folder) {
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
const gitFolder = path.join(folder, ".git")
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
try {
|
|
17
|
+
|
|
18
|
+
await fs.access(gitFolder)
|
|
19
|
+
|
|
20
|
+
} catch {
|
|
21
|
+
|
|
22
|
+
// Not a git repository
|
|
23
|
+
return null
|
|
24
|
+
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
try {
|
|
29
|
+
|
|
30
|
+
const { stdout } = await execFileAsync(
|
|
31
|
+
"git",
|
|
32
|
+
[
|
|
33
|
+
"-C",
|
|
34
|
+
folder,
|
|
35
|
+
"remote",
|
|
36
|
+
"get-url",
|
|
37
|
+
"origin"
|
|
38
|
+
]
|
|
39
|
+
)
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
return stdout.trim()
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
} catch {
|
|
46
|
+
|
|
47
|
+
return null
|
|
48
|
+
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
module.exports = getRemote
|
package/lib/matches.js
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
function matchesRepo(inputRepo, remoteRepo) {
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
// Exact match:
|
|
5
|
+
// facebook/react === facebook/react
|
|
6
|
+
if (inputRepo.full === remoteRepo.full) {
|
|
7
|
+
return true
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
// User only provided repo name:
|
|
12
|
+
// react === facebook/react
|
|
13
|
+
if (
|
|
14
|
+
inputRepo.owner === null &&
|
|
15
|
+
inputRepo.name === remoteRepo.name
|
|
16
|
+
) {
|
|
17
|
+
return true
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
return false
|
|
22
|
+
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
module.exports = matchesRepo
|
package/lib/normalize.js
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
function normalizeRepo(input) {
|
|
2
|
+
|
|
3
|
+
if (!input) {
|
|
4
|
+
return null
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
let repo = input.trim().toLowerCase()
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
// Remove .git ending
|
|
12
|
+
repo = repo.replace(/\.git$/, "")
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
// Convert SSH GitHub URLs
|
|
16
|
+
repo = repo.replace(
|
|
17
|
+
/^git@github\.com:/,
|
|
18
|
+
""
|
|
19
|
+
)
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
// Convert HTTPS GitHub URLs
|
|
23
|
+
repo = repo.replace(
|
|
24
|
+
/^https?:\/\/github\.com\//,
|
|
25
|
+
""
|
|
26
|
+
)
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
// Remove trailing slash
|
|
30
|
+
repo = repo.replace(/\/$/, "")
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
const parts = repo.split("/")
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
return {
|
|
37
|
+
full: repo,
|
|
38
|
+
name: parts[parts.length - 1],
|
|
39
|
+
owner: parts.length > 1 ? parts[parts.length - 2] : null
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
module.exports = normalizeRepo
|
package/lib/search.js
ADDED
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
const fs = require("fs/promises");
|
|
2
|
+
const path = require("path");
|
|
3
|
+
const getRemote = require("./git");
|
|
4
|
+
const normalizeRepo = require("./normalize");
|
|
5
|
+
const matchesRepo = require("./matches");
|
|
6
|
+
|
|
7
|
+
const ignoredDirectories = new Set([
|
|
8
|
+
"node_modules",
|
|
9
|
+
".git",
|
|
10
|
+
"dist",
|
|
11
|
+
"build",
|
|
12
|
+
".next",
|
|
13
|
+
"coverage",
|
|
14
|
+
]);
|
|
15
|
+
|
|
16
|
+
async function search(remoteInput) {
|
|
17
|
+
const normalizedInput = normalizeRepo(remoteInput);
|
|
18
|
+
|
|
19
|
+
const startingFolder = process.cwd();
|
|
20
|
+
|
|
21
|
+
console.log("Searching for:");
|
|
22
|
+
console.log(normalizedInput);
|
|
23
|
+
console.log("Searching...");
|
|
24
|
+
|
|
25
|
+
await searchFolder(startingFolder, normalizedInput);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
async function searchFolder(folder, normalizedInput) {
|
|
29
|
+
let entries;
|
|
30
|
+
|
|
31
|
+
try {
|
|
32
|
+
entries = await fs.readdir(folder, {
|
|
33
|
+
withFileTypes: true,
|
|
34
|
+
});
|
|
35
|
+
} catch (error) {
|
|
36
|
+
// Cannot access folder, ignore it
|
|
37
|
+
return;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
for (const entry of entries) {
|
|
41
|
+
// Skip ignored directories
|
|
42
|
+
if (entry.isDirectory() && ignoredDirectories.has(entry.name)) {
|
|
43
|
+
continue;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
const fullPath = path.join(folder, entry.name);
|
|
47
|
+
|
|
48
|
+
if (entry.isDirectory()) {
|
|
49
|
+
// Check if this directory is a git repository
|
|
50
|
+
const remote = await getRemote(fullPath);
|
|
51
|
+
|
|
52
|
+
if (remote) {
|
|
53
|
+
const normalizedRemote = normalizeRepo(remote);
|
|
54
|
+
|
|
55
|
+
if (matchesRepo(normalizedInput, normalizedRemote)) {
|
|
56
|
+
console.log("FOUND:");
|
|
57
|
+
console.log(fullPath);
|
|
58
|
+
console.log("");
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
// Continue searching deeper
|
|
63
|
+
await searchFolder(fullPath, normalizedInput);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
module.exports = search;
|
package/package.json
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "git-find-remote",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"bin":{
|
|
5
|
+
"git-find-remote": "./bin/cli.js"
|
|
6
|
+
},
|
|
7
|
+
"main": "lib/search.js",
|
|
8
|
+
"scripts": {
|
|
9
|
+
"test": "jest"
|
|
10
|
+
},
|
|
11
|
+
"keywords": [
|
|
12
|
+
"git",
|
|
13
|
+
"github",
|
|
14
|
+
"find",
|
|
15
|
+
"finder",
|
|
16
|
+
"repository",
|
|
17
|
+
".git",
|
|
18
|
+
"remote",
|
|
19
|
+
"terminal",
|
|
20
|
+
"cli"
|
|
21
|
+
],
|
|
22
|
+
"author": "OmarDevelopment",
|
|
23
|
+
"license": "MIT",
|
|
24
|
+
"description": "",
|
|
25
|
+
"repository": {
|
|
26
|
+
"type": "git",
|
|
27
|
+
"url": "https://github.com/omarakamal/git-find-remote.git",
|
|
28
|
+
"homepage": "https://github.com/omarakamal/git-find-remote/README.md"
|
|
29
|
+
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
}
|