@altano/repository-tools 0.0.2
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 +28 -0
- package/dist/exec.d.ts +6 -0
- package/dist/exec.js +11 -0
- package/dist/findRoot.d.ts +11 -0
- package/dist/findRoot.js +45 -0
- package/dist/findRootSync.d.ts +11 -0
- package/dist/findRootSync.js +45 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.js +2 -0
- package/dist/repositoryCommand.d.ts +6 -0
- package/dist/repositoryCommand.js +61 -0
- package/dist/types.d.ts +3 -0
- package/dist/types.js +9 -0
- package/package.json +70 -0
package/README.md
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
# repository-tools
|
|
2
|
+
|
|
3
|
+
Misc tools for dealing with repositories of multiple version control systems
|
|
4
|
+
|
|
5
|
+
## Supported Version Control Systems
|
|
6
|
+
|
|
7
|
+
- git
|
|
8
|
+
- mercurial
|
|
9
|
+
- sapling
|
|
10
|
+
- subversion
|
|
11
|
+
|
|
12
|
+
## Tools
|
|
13
|
+
|
|
14
|
+
### findRoot[Sync]
|
|
15
|
+
|
|
16
|
+
Given a path inside a repository, find the path of the root
|
|
17
|
+
|
|
18
|
+
Example:
|
|
19
|
+
|
|
20
|
+
```ts
|
|
21
|
+
findRootSync("/my-git-repo/some/subdirectory"); // => "/my-git-repo"
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
Example:
|
|
25
|
+
|
|
26
|
+
```ts
|
|
27
|
+
await findRoot("/my-git-repo/some/subdirectory"); // => "/my-git-repo"
|
|
28
|
+
```
|
package/dist/exec.d.ts
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
/// <reference types="node" />
|
|
2
|
+
import { exec, execFile } from "child_process";
|
|
3
|
+
export { execSync, execFileSync } from "child_process";
|
|
4
|
+
export declare const execAsync: typeof exec.__promisify__;
|
|
5
|
+
export declare const execFileAsync: typeof execFile.__promisify__;
|
|
6
|
+
//# sourceMappingURL=exec.d.ts.map
|
package/dist/exec.js
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { exec, execFile } from "child_process";
|
|
2
|
+
import { promisify } from "node:util";
|
|
3
|
+
import { execSync, execFileSync } from "child_process";
|
|
4
|
+
const execAsync = promisify(exec);
|
|
5
|
+
const execFileAsync = promisify(execFile);
|
|
6
|
+
export {
|
|
7
|
+
execAsync,
|
|
8
|
+
execFileAsync,
|
|
9
|
+
execFileSync,
|
|
10
|
+
execSync
|
|
11
|
+
};
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Find the root path of the repository containing the given directory.
|
|
3
|
+
*
|
|
4
|
+
* @returns null if not found or the path of the repository root as a string
|
|
5
|
+
*/
|
|
6
|
+
export declare function findRoot(
|
|
7
|
+
/**
|
|
8
|
+
* The directory path of anything in a version-controlled repository
|
|
9
|
+
*/
|
|
10
|
+
directory: string): Promise<string | null>;
|
|
11
|
+
//# sourceMappingURL=findRoot.d.ts.map
|
package/dist/findRoot.js
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { repositoryExec } from "./repositoryCommand";
|
|
2
|
+
async function findGitRoot(directory) {
|
|
3
|
+
return repositoryExec(directory, "git", [
|
|
4
|
+
"rev-parse",
|
|
5
|
+
"--quiet",
|
|
6
|
+
"--show-toplevel"
|
|
7
|
+
]);
|
|
8
|
+
}
|
|
9
|
+
async function findSaplingRoot(directory) {
|
|
10
|
+
return repositoryExec(directory, "sl", ["--quiet", "root"]);
|
|
11
|
+
}
|
|
12
|
+
async function findMercurialRoot(directory) {
|
|
13
|
+
return repositoryExec(directory, "hg", ["--quiet", "root"]);
|
|
14
|
+
}
|
|
15
|
+
async function findSubversionRoot(directory) {
|
|
16
|
+
return repositoryExec(directory, "svn", ["info", "--show-item", "wc-root"]);
|
|
17
|
+
}
|
|
18
|
+
const findMethods = [
|
|
19
|
+
findGitRoot,
|
|
20
|
+
// most used and fastest check
|
|
21
|
+
findSubversionRoot,
|
|
22
|
+
// next highest market share
|
|
23
|
+
findSaplingRoot,
|
|
24
|
+
// much smaller market share, but much faster
|
|
25
|
+
findMercurialRoot
|
|
26
|
+
// slow af
|
|
27
|
+
];
|
|
28
|
+
async function findRoot(directory) {
|
|
29
|
+
for (const method of findMethods) {
|
|
30
|
+
try {
|
|
31
|
+
const result = await method(directory);
|
|
32
|
+
if (result != null && result !== "") {
|
|
33
|
+
return result;
|
|
34
|
+
}
|
|
35
|
+
} catch (e) {
|
|
36
|
+
if (e instanceof Error && "code" in e && e.code === "ENOTDIR") {
|
|
37
|
+
throw new Error(`Given path isn't a directory: ${directory}`);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
return null;
|
|
42
|
+
}
|
|
43
|
+
export {
|
|
44
|
+
findRoot
|
|
45
|
+
};
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Find the root path of the repository containing the given directory.
|
|
3
|
+
*
|
|
4
|
+
* @returns null if not found or the path of the repository root as a string
|
|
5
|
+
*/
|
|
6
|
+
export declare function findRootSync(
|
|
7
|
+
/**
|
|
8
|
+
* The directory path of anything in a version-controlled repository
|
|
9
|
+
*/
|
|
10
|
+
directory: string): string | null;
|
|
11
|
+
//# sourceMappingURL=findRootSync.d.ts.map
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { repositoryExecSync } from "./repositoryCommand";
|
|
2
|
+
function findGitRoot(cwd) {
|
|
3
|
+
return repositoryExecSync(cwd, "git", [
|
|
4
|
+
"rev-parse",
|
|
5
|
+
"--quiet",
|
|
6
|
+
"--show-toplevel"
|
|
7
|
+
]);
|
|
8
|
+
}
|
|
9
|
+
function findSaplingRoot(cwd) {
|
|
10
|
+
return repositoryExecSync(cwd, "sl", ["--quiet", "root"]);
|
|
11
|
+
}
|
|
12
|
+
function findMercurialRoot(cwd) {
|
|
13
|
+
return repositoryExecSync(cwd, "hg", ["--quiet", "root"]);
|
|
14
|
+
}
|
|
15
|
+
function findSubversionRoot(cwd) {
|
|
16
|
+
return repositoryExecSync(cwd, "svn", ["info", "--show-item", "wc-root"]);
|
|
17
|
+
}
|
|
18
|
+
const findMethods = [
|
|
19
|
+
findGitRoot,
|
|
20
|
+
// most used and fastest check
|
|
21
|
+
findSubversionRoot,
|
|
22
|
+
// next highest market share
|
|
23
|
+
findSaplingRoot,
|
|
24
|
+
// much smaller market share, but much faster
|
|
25
|
+
findMercurialRoot
|
|
26
|
+
// slow af
|
|
27
|
+
];
|
|
28
|
+
function findRootSync(directory) {
|
|
29
|
+
for (const method of findMethods) {
|
|
30
|
+
try {
|
|
31
|
+
const result = method(directory);
|
|
32
|
+
if (result != null && result !== "") {
|
|
33
|
+
return result;
|
|
34
|
+
}
|
|
35
|
+
} catch (e) {
|
|
36
|
+
if (e instanceof Error && "code" in e && e.code === "ENOTDIR") {
|
|
37
|
+
throw new Error(`Given path isn't a directory: ${directory}`);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
return null;
|
|
42
|
+
}
|
|
43
|
+
export {
|
|
44
|
+
findRootSync
|
|
45
|
+
};
|
package/dist/index.d.ts
ADDED
package/dist/index.js
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
type RepositoryCommand = "git" | "hg" | "sl" | "svn" | "svnadmin" | "svnrdump";
|
|
2
|
+
export declare function repositoryExec(cwd: string, command: RepositoryCommand, args: readonly string[]): Promise<string>;
|
|
3
|
+
export declare function repositoryExecSync(cwd: string, command: RepositoryCommand, args: readonly string[]): string;
|
|
4
|
+
export declare const createExecForDirectory: (cwd: string) => (command: RepositoryCommand, args: readonly string[]) => Promise<string>;
|
|
5
|
+
export {};
|
|
6
|
+
//# sourceMappingURL=repositoryCommand.d.ts.map
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { execFileAsync, execFileSync } from "./exec";
|
|
2
|
+
const environment = {
|
|
3
|
+
git: {
|
|
4
|
+
// non-interactive
|
|
5
|
+
GIT_TERMINAL_PROMPT: "0",
|
|
6
|
+
// don't use global config
|
|
7
|
+
GIT_CONFIG_GLOBAL: "/dev/null",
|
|
8
|
+
GIT_CONFIG_SYSTEM: "/dev/null",
|
|
9
|
+
// user config
|
|
10
|
+
GIT_COMMITTER_NAME: "alan",
|
|
11
|
+
GIT_COMMITTER_EMAIL: "alan@example.com",
|
|
12
|
+
GIT_AUTHOR_NAME: "alan",
|
|
13
|
+
GIT_AUTHOR_EMAIL: "alan@example.com"
|
|
14
|
+
},
|
|
15
|
+
hg: {
|
|
16
|
+
// don't use global config
|
|
17
|
+
HGRCPATH: "/dev/null",
|
|
18
|
+
// don't use global config
|
|
19
|
+
HGUSER: "alan",
|
|
20
|
+
EMAIL: "alan@example.com"
|
|
21
|
+
},
|
|
22
|
+
sl: {
|
|
23
|
+
// don't use global config
|
|
24
|
+
HGRCPATH: "/dev/null",
|
|
25
|
+
// don't use global config
|
|
26
|
+
HGUSER: "alan",
|
|
27
|
+
EMAIL: "alan@example.com"
|
|
28
|
+
},
|
|
29
|
+
svn: {},
|
|
30
|
+
svnadmin: {},
|
|
31
|
+
svnrdump: {}
|
|
32
|
+
};
|
|
33
|
+
async function repositoryExec(cwd, command, args) {
|
|
34
|
+
return execFileAsync(command, args, {
|
|
35
|
+
cwd,
|
|
36
|
+
encoding: "utf8",
|
|
37
|
+
env: {
|
|
38
|
+
...process.env,
|
|
39
|
+
...environment[command]
|
|
40
|
+
}
|
|
41
|
+
}).then(({ stdout, stderr }) => {
|
|
42
|
+
return stderr ? Promise.reject(stderr.trim()) : stdout.trim();
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
function repositoryExecSync(cwd, command, args) {
|
|
46
|
+
const result = execFileSync(command, args, {
|
|
47
|
+
cwd,
|
|
48
|
+
encoding: "utf8",
|
|
49
|
+
env: {
|
|
50
|
+
...process.env,
|
|
51
|
+
...environment[command]
|
|
52
|
+
}
|
|
53
|
+
}).trim();
|
|
54
|
+
return result;
|
|
55
|
+
}
|
|
56
|
+
const createExecForDirectory = (cwd) => repositoryExec.bind(null, cwd);
|
|
57
|
+
export {
|
|
58
|
+
createExecForDirectory,
|
|
59
|
+
repositoryExec,
|
|
60
|
+
repositoryExecSync
|
|
61
|
+
};
|
package/dist/types.d.ts
ADDED
package/dist/types.js
ADDED
package/package.json
ADDED
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@altano/repository-tools",
|
|
3
|
+
"version": "0.0.2",
|
|
4
|
+
"description": "Misc tools for dealing with repositories of multiple version control systems (git, svn, etc)",
|
|
5
|
+
"types": "./dist/index.d.ts",
|
|
6
|
+
"exports": "./dist/index.js",
|
|
7
|
+
"type": "module",
|
|
8
|
+
"sideEffects": false,
|
|
9
|
+
"files": [
|
|
10
|
+
"dist/**/*.js",
|
|
11
|
+
"dist/**/*.d.ts"
|
|
12
|
+
],
|
|
13
|
+
"repository": {
|
|
14
|
+
"type": "git",
|
|
15
|
+
"url": "https://github.com/altano/npm-packages",
|
|
16
|
+
"directory": "packages/repository-tools"
|
|
17
|
+
},
|
|
18
|
+
"homepage": "https://github.com/altano/npm-packages/tree/main/packages/repository-tools",
|
|
19
|
+
"keywords": [
|
|
20
|
+
"repository",
|
|
21
|
+
"root",
|
|
22
|
+
"git",
|
|
23
|
+
"mercurial",
|
|
24
|
+
"sapling"
|
|
25
|
+
],
|
|
26
|
+
"author": {
|
|
27
|
+
"name": "Alan Norbauer",
|
|
28
|
+
"email": "altano@gmail.com",
|
|
29
|
+
"url": "https://alan.norbauer.com"
|
|
30
|
+
},
|
|
31
|
+
"license": "ISC",
|
|
32
|
+
"devDependencies": {
|
|
33
|
+
"@types/node": "^20.11.25",
|
|
34
|
+
"@vitest/coverage-v8": "^1.4.0",
|
|
35
|
+
"@vitest/expect": "^1.4.0",
|
|
36
|
+
"@vitest/ui": "^1.3.1",
|
|
37
|
+
"eslint": "^8.57.0",
|
|
38
|
+
"find-cache-dir": "^5.0.0",
|
|
39
|
+
"memize": "^2.1.0",
|
|
40
|
+
"npm-run-all": "^4.1.5",
|
|
41
|
+
"prettier": "^3.2.5",
|
|
42
|
+
"ts-assert-unreachable": "^0.0.9",
|
|
43
|
+
"typescript": "^5.4.2",
|
|
44
|
+
"vite": "^5.2.8",
|
|
45
|
+
"vitest": "^1.4.0",
|
|
46
|
+
"@altano/tsconfig": "0.0.0",
|
|
47
|
+
"@altano/vitest-plugins": "0.1.0",
|
|
48
|
+
"eslint-config-altano": "0.0.0"
|
|
49
|
+
},
|
|
50
|
+
"publishConfig": {
|
|
51
|
+
"access": "public"
|
|
52
|
+
},
|
|
53
|
+
"scripts": {
|
|
54
|
+
"build": "tsup --config build-config/tsup.config.node.ts",
|
|
55
|
+
"build:types": "tsc --project tsconfig.declarations.json",
|
|
56
|
+
"clean": "rm -rf .turbo && rm -rf .tsbuildinfo && rm -rf node_modules && rm -rf dist",
|
|
57
|
+
"dev": "pnpm run build --watch",
|
|
58
|
+
"format": "prettier --check src",
|
|
59
|
+
"format:fix": "prettier --write src",
|
|
60
|
+
"lint": "eslint package.json src/**/*.ts*",
|
|
61
|
+
"lint:fix": "TIMING=1 pnpm lint --fix",
|
|
62
|
+
"lint:timing": "TIMING=1 pnpm lint",
|
|
63
|
+
"test:build": "./tests/scripts/createRepositoryBundles.ts",
|
|
64
|
+
"test:unit": "run-s test:unit:run test:unit:benchmark",
|
|
65
|
+
"test:unit:benchmark": "vitest --run bench",
|
|
66
|
+
"test:unit:run": "vitest --run",
|
|
67
|
+
"test:unit:watch": "vitest",
|
|
68
|
+
"typecheck": "tsc --noEmit"
|
|
69
|
+
}
|
|
70
|
+
}
|