@huozi-ai/git-kit 0.1.0-alpha.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.
Files changed (51) hide show
  1. package/LICENSE +202 -0
  2. package/NOTICE +6 -0
  3. package/dist/commands.d.ts +17 -0
  4. package/dist/commands.d.ts.map +1 -0
  5. package/dist/commands.js +62 -0
  6. package/dist/commands.js.map +1 -0
  7. package/dist/configure.d.ts +43 -0
  8. package/dist/configure.d.ts.map +1 -0
  9. package/dist/configure.js +146 -0
  10. package/dist/configure.js.map +1 -0
  11. package/dist/credential.d.ts +40 -0
  12. package/dist/credential.d.ts.map +1 -0
  13. package/dist/credential.js +61 -0
  14. package/dist/credential.js.map +1 -0
  15. package/dist/git.d.ts +50 -0
  16. package/dist/git.d.ts.map +1 -0
  17. package/dist/git.js +71 -0
  18. package/dist/git.js.map +1 -0
  19. package/dist/index.d.ts +18 -0
  20. package/dist/index.d.ts.map +1 -0
  21. package/dist/index.js +11 -0
  22. package/dist/index.js.map +1 -0
  23. package/dist/lfs/client.d.ts +47 -0
  24. package/dist/lfs/client.d.ts.map +1 -0
  25. package/dist/lfs/client.js +216 -0
  26. package/dist/lfs/client.js.map +1 -0
  27. package/dist/lfs/filter.d.ts +39 -0
  28. package/dist/lfs/filter.d.ts.map +1 -0
  29. package/dist/lfs/filter.js +148 -0
  30. package/dist/lfs/filter.js.map +1 -0
  31. package/dist/lfs/pktline.d.ts +33 -0
  32. package/dist/lfs/pktline.d.ts.map +1 -0
  33. package/dist/lfs/pktline.js +127 -0
  34. package/dist/lfs/pktline.js.map +1 -0
  35. package/dist/lfs/pointer.d.ts +20 -0
  36. package/dist/lfs/pointer.d.ts.map +1 -0
  37. package/dist/lfs/pointer.js +56 -0
  38. package/dist/lfs/pointer.js.map +1 -0
  39. package/dist/lfs/push.d.ts +20 -0
  40. package/dist/lfs/push.d.ts.map +1 -0
  41. package/dist/lfs/push.js +94 -0
  42. package/dist/lfs/push.js.map +1 -0
  43. package/dist/lfs/store.d.ts +28 -0
  44. package/dist/lfs/store.d.ts.map +1 -0
  45. package/dist/lfs/store.js +98 -0
  46. package/dist/lfs/store.js.map +1 -0
  47. package/dist/ops.d.ts +39 -0
  48. package/dist/ops.d.ts.map +1 -0
  49. package/dist/ops.js +130 -0
  50. package/dist/ops.js.map +1 -0
  51. package/package.json +39 -0
package/dist/ops.js ADDED
@@ -0,0 +1,130 @@
1
+ import { mkdir } from "node:fs/promises";
2
+ import { commandLine, configureRepo, } from "./configure.js";
3
+ import { gitConfig, GitCommandError, GitKitError, runGit } from "./git.js";
4
+ import { LfsClient, lfsEndpoint } from "./lfs/client.js";
5
+ import { pointersBetween } from "./lfs/push.js";
6
+ import { LocalObjects } from "./lfs/store.js";
7
+ const REMOTE = "origin";
8
+ function identityArgs(author) {
9
+ return author
10
+ ? ["-c", `user.name=${author.name}`, "-c", `user.email=${author.email}`]
11
+ : [];
12
+ }
13
+ async function hasRemote(dir) {
14
+ return (await gitConfig(dir, `remote.${REMOTE}.url`)) !== undefined;
15
+ }
16
+ async function resolve(dir, ref) {
17
+ if (ref.startsWith("-"))
18
+ throw new GitKitError("invalid", `Invalid ref: ${ref}`);
19
+ const { code, stdout } = await runGit(["rev-parse", "--verify", "--quiet", `${ref}^{commit}`], {
20
+ cwd: dir,
21
+ okCodes: [1, 128],
22
+ });
23
+ return code === 0 ? stdout.toString("utf8").trim() : null;
24
+ }
25
+ /** The current branch. Throws `detached` when HEAD is not on a branch. */
26
+ export async function currentBranch(dir) {
27
+ const { code, stdout } = await runGit(["symbolic-ref", "--quiet", "--short", "HEAD"], { cwd: dir, okCodes: [1, 128] });
28
+ if (code !== 0)
29
+ throw new GitKitError("detached", "Not on a revision branch");
30
+ return stdout.toString("utf8").trim();
31
+ }
32
+ /** Uploads the LFS objects of commits the remote does not have yet. Returns how many were sent. */
33
+ export async function uploadMedia(dir, refs = ["HEAD"]) {
34
+ const pointers = await pointersBetween(dir, refs, [], REMOTE);
35
+ if (pointers.length === 0)
36
+ return 0;
37
+ const client = new LfsClient(dir, await lfsEndpoint(dir, REMOTE), await LocalObjects.open(dir));
38
+ return client.upload(pointers);
39
+ }
40
+ function pushError(branch, error) {
41
+ const stderr = error instanceof GitCommandError ? error.stderr : String(error);
42
+ if (/pre-receive hook declined|may not update|protected branch/i.test(stderr)) {
43
+ return new GitKitError("push_denied", `You cannot save to ${branch} directly; start a revision first`, { cause: error });
44
+ }
45
+ if (/non-fast-forward|fetch first|\[rejected\]|failed to push some refs/i.test(stderr)) {
46
+ return new GitKitError("push_rejected", `Someone else saved ${branch} first; sync, then save again`, { cause: error });
47
+ }
48
+ if (/Authentication failed|403|401/i.test(stderr)) {
49
+ return new GitKitError("auth", `Not allowed to save: ${stderr.trim()}`, {
50
+ cause: error,
51
+ });
52
+ }
53
+ return error instanceof GitKitError
54
+ ? error
55
+ : new GitKitError("git", stderr, { cause: error });
56
+ }
57
+ /** Stages everything, commits, uploads new media and pushes the current branch. */
58
+ export async function save({ dir, message, author, }) {
59
+ const branch = await currentBranch(dir);
60
+ await runGit(["add", "--all"], { cwd: dir });
61
+ const { code: clean } = await runGit(["diff", "--cached", "--quiet"], {
62
+ cwd: dir,
63
+ okCodes: [1],
64
+ });
65
+ const committed = clean === 1;
66
+ if (committed)
67
+ await runGit([...identityArgs(author), "commit", "--quiet", "-F", "-"], {
68
+ cwd: dir,
69
+ input: message,
70
+ });
71
+ const sha = await resolve(dir, "HEAD");
72
+ if (!sha)
73
+ return { committed, branch, sha: "", pushed: false, uploaded: 0 };
74
+ if (!(await hasRemote(dir)))
75
+ return { committed, branch, sha, pushed: false, uploaded: 0 };
76
+ // Upload media first, so saving works even where the pre-push hook is not installed.
77
+ const uploaded = await uploadMedia(dir);
78
+ try {
79
+ await runGit([
80
+ "push",
81
+ "--quiet",
82
+ "--set-upstream",
83
+ REMOTE,
84
+ `HEAD:refs/heads/${branch}`,
85
+ ], { cwd: dir });
86
+ }
87
+ catch (error) {
88
+ throw pushError(branch, error);
89
+ }
90
+ return { committed, branch, sha, pushed: true, uploaded };
91
+ }
92
+ /**
93
+ * Clones a repository with our credential helper and LFS client from the start: clone without
94
+ * checkout, configure, then check out (media downloads through the smudge filter).
95
+ */
96
+ export async function clone({ url, dir, branch, ...options }) {
97
+ await mkdir(dir, { recursive: true });
98
+ let host;
99
+ try {
100
+ host = new URL(url).origin;
101
+ }
102
+ catch {
103
+ host = undefined;
104
+ }
105
+ const helper = host && options.credentials !== false
106
+ ? [
107
+ "-c",
108
+ `credential.${host}.helper=`,
109
+ "-c",
110
+ `credential.${host}.helper=!${commandLine(options, "git-credential")}`,
111
+ "-c",
112
+ `credential.${host}.useHttpPath=true`,
113
+ ]
114
+ : [];
115
+ await runGit([
116
+ ...helper,
117
+ "clone",
118
+ "--quiet",
119
+ "--no-checkout",
120
+ ...(branch ? ["--branch", branch] : []),
121
+ "--",
122
+ url,
123
+ ".",
124
+ ], { cwd: dir });
125
+ await configureRepo(dir, { ...options, attributes: false });
126
+ // An empty remote has no HEAD yet: nothing to check out.
127
+ if (await resolve(dir, "HEAD"))
128
+ await runGit(["reset", "--quiet", "--hard", "HEAD"], { cwd: dir });
129
+ }
130
+ //# sourceMappingURL=ops.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ops.js","sourceRoot":"","sources":["../src/ops.ts"],"names":[],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,39 @@
1
+ {
2
+ "name": "@huozi-ai/git-kit",
3
+ "version": "0.1.0-alpha.0",
4
+ "license": "Apache-2.0",
5
+ "description": "Client-side git for people who never touch git: a credential helper that fetches short-lived tokens, a Git LFS client (clean, smudge, pre-push), and clone and save on top of the git binary.",
6
+ "type": "module",
7
+ "exports": {
8
+ ".": {
9
+ "types": "./dist/index.d.ts",
10
+ "import": "./dist/index.js"
11
+ }
12
+ },
13
+ "files": [
14
+ "NOTICE",
15
+ "dist"
16
+ ],
17
+ "devDependencies": {
18
+ "@types/node": "^24.0.0",
19
+ "eslint": "^9.39.4",
20
+ "rimraf": "^6.1.3",
21
+ "tsx": "^4.23.15",
22
+ "typescript": "~5.9.3",
23
+ "@huozi-ai/eslint-config": "0.0.0",
24
+ "@huozi-ai/typescript-config": "0.0.0",
25
+ "@huozi-ai/repo-host": "0.1.0"
26
+ },
27
+ "publishConfig": {
28
+ "access": "public"
29
+ },
30
+ "engines": {
31
+ "node": ">=22.19"
32
+ },
33
+ "scripts": {
34
+ "build": "rimraf dist && tsc -b",
35
+ "typecheck": "tsc -p tsconfig.json --noEmit && tsc -p test/tsconfig.json",
36
+ "lint": "eslint . --max-warnings 0",
37
+ "test": "node --import tsx --test \"test/**/*.test.ts\""
38
+ }
39
+ }