resulgit 1.0.12 → 1.0.14

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 (2) hide show
  1. package/package.json +1 -1
  2. package/resulgit.js +62 -2
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "resulgit",
3
- "version": "1.0.12",
3
+ "version": "1.0.14",
4
4
  "description": "A powerful CLI tool for version control system operations - clone, commit, push, pull, merge, branch management, and more",
5
5
  "main": "resulgit.js",
6
6
  "bin": {
package/resulgit.js CHANGED
@@ -100,6 +100,43 @@ async function request(method, url, body, token) {
100
100
  return res.text()
101
101
  }
102
102
 
103
+ /**
104
+ * Upload files as blobs via multipart form data
105
+ * @param {string} server - Server URL
106
+ * @param {string} repoId - Repository ID
107
+ * @param {Record<string, string>} files - Map of file paths to content
108
+ * @param {string} token - Auth token
109
+ * @returns {Promise<Record<string, string>>} Map of file paths to blob IDs
110
+ */
111
+ async function uploadBlobs(server, repoId, files, token) {
112
+ const FormData = (await import('node:buffer')).File ? globalThis.FormData : (await import('undici')).FormData
113
+ const formData = new FormData()
114
+
115
+ for (const [filePath, content] of Object.entries(files)) {
116
+ // Create a Blob/File from the content
117
+ const blob = new Blob([content], { type: 'text/plain' })
118
+ formData.append('files', blob, filePath)
119
+ }
120
+
121
+ const url = new URL(`/api/repositories/${repoId}/blobs`, server).toString()
122
+ const headers = {}
123
+ if (token) headers['Authorization'] = `Bearer ${token}`
124
+
125
+ const res = await fetch(url, {
126
+ method: 'POST',
127
+ headers,
128
+ body: formData
129
+ })
130
+
131
+ if (!res.ok) {
132
+ const text = await res.text()
133
+ throw new Error(`Blob upload failed: ${res.status} ${res.statusText} ${text}`)
134
+ }
135
+
136
+ const data = await res.json()
137
+ return data.blobs || {}
138
+ }
139
+
103
140
  function print(obj, json) {
104
141
  if (json) {
105
142
  process.stdout.write(JSON.stringify(obj, null, 2) + '\n')
@@ -1429,8 +1466,31 @@ async function cmdPush(opts) {
1429
1466
  // Hook doesn't exist or other error, continue
1430
1467
  }
1431
1468
 
1432
- const body = { message: localMeta.pendingCommit?.message || (opts.message || 'Push'), files: merged, branchName: remoteMeta.branch }
1433
- spinnerUpdate(spinner, `Pushing ${Object.keys(merged).length} file(s) to '${remoteMeta.branch}'...`)
1469
+ // Step 1: Upload files as blobs
1470
+ spinnerUpdate(spinner, `Uploading ${Object.keys(merged).length} file(s)...`)
1471
+ let blobMap = {}
1472
+ try {
1473
+ blobMap = await uploadBlobs(server, remoteMeta.repoId, merged, token)
1474
+ } catch (err) {
1475
+ // If blob upload fails, fall back to sending content directly
1476
+ // (This handles servers that accept content in commits endpoint)
1477
+ spinnerUpdate(spinner, 'Blob upload not available, sending files directly...')
1478
+ blobMap = merged // Use content directly
1479
+ }
1480
+
1481
+ // Step 2: Create commit with blob IDs (or content if blob upload failed)
1482
+ const commitFiles = {}
1483
+ for (const [filePath, content] of Object.entries(merged)) {
1484
+ // Use blob ID if available, otherwise use content
1485
+ commitFiles[filePath] = blobMap[filePath] || content
1486
+ }
1487
+
1488
+ const body = {
1489
+ message: localMeta.pendingCommit?.message || (opts.message || 'Push'),
1490
+ files: commitFiles,
1491
+ branchName: remoteMeta.branch
1492
+ }
1493
+ spinnerUpdate(spinner, `Creating commit on '${remoteMeta.branch}'...`)
1434
1494
  const url = new URL(`/api/repositories/${remoteMeta.repoId}/commits`, server).toString()
1435
1495
  const data = await request('POST', url, body, token)
1436
1496
  localMeta.baseCommitId = data.id || remote.commitId || ''