gent-cli 1.8.0 → 2.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "gent-cli",
3
- "version": "1.8.0",
3
+ "version": "2.0.0",
4
4
  "description": "A modern, Git-like version control CLI with built-in cloud authentication and global user identity management.",
5
5
  "main": "src/index.js",
6
6
  "bin": {
@@ -76,14 +76,17 @@ async function create(repoName, options) {
76
76
  'main'
77
77
  );
78
78
 
79
- spinner.succeed(chalk.green(`Repository created: ${repository.name}`));
79
+ const ownerId = repository.owner_id || repository.owner?.id || repository.owner;
80
+ const name = repository.name || repository.project_name || repoName;
81
+
82
+ spinner.succeed(chalk.green(`Repository created: ${name}`));
80
83
 
81
84
  console.log(chalk.cyan('\nRepository Details:'));
82
- console.log(chalk.gray(' Name:'), repository.name);
83
- console.log(chalk.gray(' Owner:'), repository.owner_email);
85
+ console.log(chalk.gray(' Name:'), name);
86
+ console.log(chalk.gray(' Owner:'), ownerId);
84
87
  console.log(chalk.gray(' Private:'), repository.is_private ? 'Yes' : 'No');
85
88
  console.log(chalk.gray(' Description:'), repository.description || '(none)');
86
- console.log(chalk.gray(' Created:'), new Date(repository.created_at).toLocaleString());
89
+ console.log(chalk.gray(' Created:'), new Date(repository.created_at || repository.created || new Date()).toLocaleString());
87
90
 
88
91
  // Initialize local repository if requested
89
92
  if (options.initLocal) {
@@ -96,7 +99,7 @@ async function create(repoName, options) {
96
99
  await ensureDir(path.join(gentPath, 'refs', 'heads'));
97
100
 
98
101
  // Add remote
99
- await addRemote('origin', repository.owner_id, repository.name, cwd);
102
+ await addRemote('origin', ownerId, name, cwd);
100
103
 
101
104
  console.log(chalk.green('\n✓ Local repository initialized and remote added'));
102
105
  console.log(chalk.yellow('\nNext steps:'));
@@ -127,8 +127,11 @@ node_modules/
127
127
  'main'
128
128
  );
129
129
 
130
- await addRemote('origin', repository.owner_id, repository.name, cwd);
131
- spinner.succeed(chalk.green(`Created cloud repository: ${repository.owner_id}/${repository.name}`));
130
+ const ownerId = repository.owner_id || repository.owner?.id || repository.owner;
131
+ const name = repository.name || repository.project_name || repoName;
132
+
133
+ await addRemote('origin', ownerId, name, cwd);
134
+ spinner.succeed(chalk.green(`Created cloud repository: ${ownerId}/${name}`));
132
135
  console.log(chalk.gray(`Remote 'origin' added`));
133
136
  } catch (error) {
134
137
  console.log(chalk.red(`\nFailed to create cloud repository: ${error.message}`));
@@ -73,11 +73,12 @@ async function push(remoteName, branchName, options) {
73
73
  let currentSha = branchCommitSha;
74
74
 
75
75
  while (currentSha) {
76
- const commit = commits.find(c => c.sha === currentSha);
76
+ const commit = commits.find(c => (c.sha || c.hash) === currentSha);
77
77
  if (!commit) break;
78
78
 
79
79
  commitsToPush.unshift(commit); // Add to beginning to maintain order
80
- currentSha = commit.parent ? commit.parent[0] : null;
80
+ const parents = Array.isArray(commit.parent) ? commit.parent : (commit.parent ? [commit.parent] : []);
81
+ currentSha = parents.length > 0 ? parents[0] : null;
81
82
  }
82
83
 
83
84
  if (commitsToPush.length === 0) {
@@ -32,6 +32,7 @@ async function createRepository(name, description = '', isPrivate = false, defau
32
32
  try {
33
33
  const response = await apiClient.post(API_ENDPOINTS.REPOS_CREATE, {
34
34
  name,
35
+ project_name: name, // Add project_name as well for consistency
35
36
  description,
36
37
  is_private: isPrivate,
37
38
  default_branch: defaultBranch
@@ -58,12 +59,12 @@ async function listRepositories() {
58
59
  /**
59
60
  * Get repository details
60
61
  * @param {number} ownerId - Owner user ID
61
- * @param {string} repoName - Repository name
62
+ * @param {string} projectName - Project name
62
63
  * @returns {Promise<Object>} Repository data
63
64
  */
64
- async function getRepository(ownerId, repoName) {
65
+ async function getRepository(ownerId, projectName) {
65
66
  try {
66
- const url = buildUrl(API_ENDPOINTS.REPOS_GET, { owner_id: ownerId, repo_name: repoName });
67
+ const url = buildUrl(API_ENDPOINTS.REPOS_GET, { owner_id: ownerId, project_name: projectName });
67
68
  const response = await apiClient.get(url);
68
69
  return response;
69
70
  } catch (error) {
@@ -74,12 +75,12 @@ async function getRepository(ownerId, repoName) {
74
75
  /**
75
76
  * Delete a repository
76
77
  * @param {number} ownerId - Owner user ID
77
- * @param {string} repoName - Repository name
78
+ * @param {string} projectName - Project name
78
79
  * @returns {Promise<Object>} Delete response
79
80
  */
80
- async function deleteRepository(ownerId, repoName) {
81
+ async function deleteRepository(ownerId, projectName) {
81
82
  try {
82
- const url = buildUrl(API_ENDPOINTS.REPOS_DELETE, { owner_id: ownerId, repo_name: repoName });
83
+ const url = buildUrl(API_ENDPOINTS.REPOS_DELETE, { owner_id: ownerId, project_name: projectName });
83
84
  const response = await apiClient.delete(url);
84
85
  return response;
85
86
  } catch (error) {
@@ -90,14 +91,14 @@ async function deleteRepository(ownerId, repoName) {
90
91
  /**
91
92
  * Create a blob (file content) in the repository
92
93
  * @param {number} ownerId - Owner user ID
93
- * @param {string} repoName - Repository name
94
+ * @param {string} projectName - Project name
94
95
  * @param {string} content - File content
95
96
  * @param {string} encoding - Encoding type (utf-8 or base64)
96
97
  * @returns {Promise<Object>} Created blob data
97
98
  */
98
- async function createBlob(ownerId, repoName, content, encoding = 'utf-8') {
99
+ async function createBlob(ownerId, projectName, content, encoding = 'utf-8') {
99
100
  try {
100
- const url = buildUrl(API_ENDPOINTS.BLOB_CREATE, { owner_id: ownerId, repo_name: repoName });
101
+ const url = buildUrl(API_ENDPOINTS.BLOB_CREATE, { owner_id: ownerId, project_name: projectName });
101
102
  const response = await apiClient.post(url, {
102
103
  content,
103
104
  encoding
@@ -111,13 +112,13 @@ async function createBlob(ownerId, repoName, content, encoding = 'utf-8') {
111
112
  /**
112
113
  * Get a blob by SHA
113
114
  * @param {number} ownerId - Owner user ID
114
- * @param {string} repoName - Repository name
115
+ * @param {string} projectName - Project name
115
116
  * @param {string} sha - Blob SHA
116
117
  * @returns {Promise<Object>} Blob data
117
118
  */
118
- async function getBlob(ownerId, repoName, sha) {
119
+ async function getBlob(ownerId, projectName, sha) {
119
120
  try {
120
- const url = buildUrl(API_ENDPOINTS.BLOB_GET, { owner_id: ownerId, repo_name: repoName, sha });
121
+ const url = buildUrl(API_ENDPOINTS.BLOB_GET, { owner_id: ownerId, project_name: projectName, sha });
121
122
  const response = await apiClient.get(url);
122
123
  return response;
123
124
  } catch (error) {
@@ -128,13 +129,13 @@ async function getBlob(ownerId, repoName, sha) {
128
129
  /**
129
130
  * Create a tree (directory structure) in the repository
130
131
  * @param {number} ownerId - Owner user ID
131
- * @param {string} repoName - Repository name
132
+ * @param {string} projectName - Project name
132
133
  * @param {Array} entries - Tree entries
133
134
  * @returns {Promise<Object>} Created tree data
134
135
  */
135
- async function createTree(ownerId, repoName, entries) {
136
+ async function createTree(ownerId, projectName, entries) {
136
137
  try {
137
- const url = buildUrl(API_ENDPOINTS.TREE_CREATE, { owner_id: ownerId, repo_name: repoName });
138
+ const url = buildUrl(API_ENDPOINTS.TREE_CREATE, { owner_id: ownerId, project_name: projectName });
138
139
  const response = await apiClient.post(url, {
139
140
  entries
140
141
  });
@@ -147,13 +148,13 @@ async function createTree(ownerId, repoName, entries) {
147
148
  /**
148
149
  * Get a tree by SHA
149
150
  * @param {number} ownerId - Owner user ID
150
- * @param {string} repoName - Repository name
151
+ * @param {string} projectName - Project name
151
152
  * @param {string} sha - Tree SHA
152
153
  * @returns {Promise<Object>} Tree data
153
154
  */
154
- async function getTree(ownerId, repoName, sha) {
155
+ async function getTree(ownerId, projectName, sha) {
155
156
  try {
156
- const url = buildUrl(API_ENDPOINTS.TREE_GET, { owner_id: ownerId, repo_name: repoName, sha });
157
+ const url = buildUrl(API_ENDPOINTS.TREE_GET, { owner_id: ownerId, project_name: projectName, sha });
157
158
  const response = await apiClient.get(url);
158
159
  return response;
159
160
  } catch (error) {
@@ -164,13 +165,13 @@ async function getTree(ownerId, repoName, sha) {
164
165
  /**
165
166
  * Create a commit in the repository
166
167
  * @param {number} ownerId - Owner user ID
167
- * @param {string} repoName - Repository name
168
+ * @param {string} projectName - Project name
168
169
  * @param {Object} commitData - Commit data (message, tree_sha, parent_shas, author_name, author_email, branch)
169
170
  * @returns {Promise<Object>} Created commit data
170
171
  */
171
- async function createCommit(ownerId, repoName, commitData) {
172
+ async function createCommit(ownerId, projectName, commitData) {
172
173
  try {
173
- const url = buildUrl(API_ENDPOINTS.COMMITS_CREATE, { owner_id: ownerId, repo_name: repoName });
174
+ const url = buildUrl(API_ENDPOINTS.COMMITS_CREATE, { owner_id: ownerId, project_name: projectName });
174
175
  const response = await apiClient.post(url, commitData);
175
176
  return response;
176
177
  } catch (error) {
@@ -181,12 +182,12 @@ async function createCommit(ownerId, repoName, commitData) {
181
182
  /**
182
183
  * List all commits in a repository
183
184
  * @param {number} ownerId - Owner user ID
184
- * @param {string} repoName - Repository name
185
+ * @param {string} projectName - Project name
185
186
  * @returns {Promise<Array>} List of commits
186
187
  */
187
- async function listCommits(ownerId, repoName) {
188
+ async function listCommits(ownerId, projectName) {
188
189
  try {
189
- const url = buildUrl(API_ENDPOINTS.COMMITS_LIST, { owner_id: ownerId, repo_name: repoName });
190
+ const url = buildUrl(API_ENDPOINTS.COMMITS_LIST, { owner_id: ownerId, project_name: projectName });
190
191
  const response = await apiClient.get(url);
191
192
  return response;
192
193
  } catch (error) {
@@ -197,13 +198,13 @@ async function listCommits(ownerId, repoName) {
197
198
  /**
198
199
  * Get a commit by SHA
199
200
  * @param {number} ownerId - Owner user ID
200
- * @param {string} repoName - Repository name
201
+ * @param {string} projectName - Project name
201
202
  * @param {string} sha - Commit SHA
202
203
  * @returns {Promise<Object>} Commit data
203
204
  */
204
- async function getCommit(ownerId, repoName, sha) {
205
+ async function getCommit(ownerId, projectName, sha) {
205
206
  try {
206
- const url = buildUrl(API_ENDPOINTS.COMMITS_GET, { owner_id: ownerId, repo_name: repoName, sha });
207
+ const url = buildUrl(API_ENDPOINTS.COMMITS_GET, { owner_id: ownerId, project_name: projectName, sha });
207
208
  const response = await apiClient.get(url);
208
209
  return response;
209
210
  } catch (error) {
@@ -214,14 +215,14 @@ async function getCommit(ownerId, repoName, sha) {
214
215
  /**
215
216
  * Create a branch in the repository
216
217
  * @param {number} ownerId - Owner user ID
217
- * @param {string} repoName - Repository name
218
+ * @param {string} projectName - Project name
218
219
  * @param {string} branchName - Branch name
219
220
  * @param {string} commitSha - Commit SHA to point the branch to
220
221
  * @returns {Promise<Object>} Created branch data
221
222
  */
222
- async function createBranch(ownerId, repoName, branchName, commitSha) {
223
+ async function createBranch(ownerId, projectName, branchName, commitSha) {
223
224
  try {
224
- const url = buildUrl(API_ENDPOINTS.BRANCHES_CREATE, { owner_id: ownerId, repo_name: repoName });
225
+ const url = buildUrl(API_ENDPOINTS.BRANCHES_CREATE, { owner_id: ownerId, project_name: projectName });
225
226
  const response = await apiClient.post(url, {
226
227
  name: branchName,
227
228
  commit_sha: commitSha
@@ -235,12 +236,12 @@ async function createBranch(ownerId, repoName, branchName, commitSha) {
235
236
  /**
236
237
  * List all branches in a repository
237
238
  * @param {number} ownerId - Owner user ID
238
- * @param {string} repoName - Repository name
239
+ * @param {string} projectName - Project name
239
240
  * @returns {Promise<Array>} List of branches
240
241
  */
241
- async function listBranches(ownerId, repoName) {
242
+ async function listBranches(ownerId, projectName) {
242
243
  try {
243
- const url = buildUrl(API_ENDPOINTS.BRANCHES_LIST, { owner_id: ownerId, repo_name: repoName });
244
+ const url = buildUrl(API_ENDPOINTS.BRANCHES_LIST, { owner_id: ownerId, project_name: projectName });
244
245
  const response = await apiClient.get(url);
245
246
  return response;
246
247
  } catch (error) {
@@ -251,13 +252,13 @@ async function listBranches(ownerId, repoName) {
251
252
  /**
252
253
  * Get a branch by name
253
254
  * @param {number} ownerId - Owner user ID
254
- * @param {string} repoName - Repository name
255
+ * @param {string} projectName - Project name
255
256
  * @param {string} branchName - Branch name
256
257
  * @returns {Promise<Object>} Branch data
257
258
  */
258
- async function getBranch(ownerId, repoName, branchName) {
259
+ async function getBranch(ownerId, projectName, branchName) {
259
260
  try {
260
- const url = buildUrl(API_ENDPOINTS.BRANCHES_GET, { owner_id: ownerId, repo_name: repoName, branch_name: branchName });
261
+ const url = buildUrl(API_ENDPOINTS.BRANCHES_GET, { owner_id: ownerId, project_name: projectName, branch_name: branchName });
261
262
  const response = await apiClient.get(url);
262
263
  return response;
263
264
  } catch (error) {
@@ -125,7 +125,7 @@ async function uploadCommit(commit, treeSha, ownerId, repoName, branchName) {
125
125
  const commitData = {
126
126
  message: commit.message,
127
127
  tree_sha: treeSha,
128
- parent_shas: commit.parent || [],
128
+ parent_shas: Array.isArray(commit.parent) ? commit.parent : (commit.parent ? [commit.parent] : []),
129
129
  author_name: commit.author.name,
130
130
  author_email: commit.author.email,
131
131
  branch: branchName
@@ -161,11 +161,12 @@ async function syncCommitsToCloud(commits, ownerId, repoName, branchName, cwd) {
161
161
 
162
162
  // Read files from commit
163
163
  const files = [];
164
- for (const [filePath, fileSha] of Object.entries(commit.files || {})) {
165
- const objectPath = path.join(cwd, GENT_DIR, OBJECTS_DIR, fileSha);
164
+ const commitFiles = Array.isArray(commit.files) ? commit.files : [];
165
+ for (const file of commitFiles) {
166
+ const objectPath = path.join(cwd, GENT_DIR, OBJECTS_DIR, file.hash);
166
167
  if (await pathExists(objectPath)) {
167
168
  const content = await fs.readFile(objectPath, 'utf-8');
168
- files.push({ path: filePath, content });
169
+ files.push({ path: file.path, content });
169
170
  }
170
171
  }
171
172
 
@@ -27,26 +27,26 @@ module.exports = {
27
27
  // Repository endpoints
28
28
  REPOS_LIST: '/api/repos/',
29
29
  REPOS_CREATE: '/api/repos/create/',
30
- REPOS_GET: '/api/repos/{owner_id}/{repo_name}/',
31
- REPOS_DELETE: '/api/repos/{owner_id}/{repo_name}/delete/',
30
+ REPOS_GET: '/api/repos/{owner_id}/{project_name}/',
31
+ REPOS_DELETE: '/api/repos/{owner_id}/{project_name}/delete/',
32
32
 
33
33
  // Blob endpoints
34
- BLOB_GET: '/api/repos/{owner_id}/{repo_name}/blob/{sha}/',
35
- BLOB_CREATE: '/api/repos/{owner_id}/{repo_name}/blob/create/',
34
+ BLOB_GET: '/api/repos/{owner_id}/{project_name}/blob/{sha}/',
35
+ BLOB_CREATE: '/api/repos/{owner_id}/{project_name}/blob/create/',
36
36
 
37
37
  // Tree endpoints
38
- TREE_GET: '/api/repos/{owner_id}/{repo_name}/tree/{sha}/',
39
- TREE_CREATE: '/api/repos/{owner_id}/{repo_name}/tree/create/',
38
+ TREE_GET: '/api/repos/{owner_id}/{project_name}/tree/{sha}/',
39
+ TREE_CREATE: '/api/repos/{owner_id}/{project_name}/tree/create/',
40
40
 
41
41
  // Commit endpoints
42
- COMMITS_LIST: '/api/repos/{owner_id}/{repo_name}/commits/',
43
- COMMITS_GET: '/api/repos/{owner_id}/{repo_name}/commits/{sha}/',
44
- COMMITS_CREATE: '/api/repos/{owner_id}/{repo_name}/commits/create/',
42
+ COMMITS_LIST: '/api/repos/{owner_id}/{project_name}/commits/',
43
+ COMMITS_GET: '/api/repos/{owner_id}/{project_name}/commits/{sha}/',
44
+ COMMITS_CREATE: '/api/repos/{owner_id}/{project_name}/commits/create/',
45
45
 
46
46
  // Branch endpoints
47
- BRANCHES_LIST: '/api/repos/{owner_id}/{repo_name}/branches/',
48
- BRANCHES_GET: '/api/repos/{owner_id}/{repo_name}/branches/{branch_name}/',
49
- BRANCHES_CREATE: '/api/repos/{owner_id}/{repo_name}/branches/create/'
47
+ BRANCHES_LIST: '/api/repos/{owner_id}/{project_name}/branches/',
48
+ BRANCHES_GET: '/api/repos/{owner_id}/{project_name}/branches/{branch_name}/',
49
+ BRANCHES_CREATE: '/api/repos/{owner_id}/{project_name}/branches/create/'
50
50
  },
51
51
 
52
52
  // Default ignore patterns
@@ -113,23 +113,31 @@ async function getAllFiles(dir, ignorePatterns = []) {
113
113
  */
114
114
  function shouldIgnore(filePath, patterns) {
115
115
  const normalizedPath = filePath.replace(/\\/g, '/');
116
+ const segments = normalizedPath.split('/');
116
117
 
117
118
  for (const pattern of patterns) {
118
- // Exact match
119
- if (normalizedPath === pattern || normalizedPath.startsWith(pattern + '/')) {
119
+ const normalizedPattern = pattern.replace(/\/$/, '');
120
+
121
+ // Check if any segment matches the pattern (for directory-level ignores like node_modules)
122
+ if (segments.some(segment => segment === normalizedPattern)) {
123
+ return true;
124
+ }
125
+
126
+ // Exact match or starts with pattern
127
+ if (normalizedPath === normalizedPattern || normalizedPath.startsWith(normalizedPattern + '/')) {
120
128
  return true;
121
129
  }
122
130
 
123
131
  // Wildcard match
124
- if (pattern.includes('*')) {
125
- const regex = new RegExp('^' + pattern.replace(/\*/g, '.*') + '$');
132
+ if (normalizedPattern.includes('*')) {
133
+ const regex = new RegExp('^' + normalizedPattern.replace(/\*/g, '.*') + '$');
126
134
  if (regex.test(normalizedPath)) {
127
135
  return true;
128
136
  }
129
137
  }
130
138
 
131
139
  // Extension match
132
- if (pattern.startsWith('*.') && normalizedPath.endsWith(pattern.substring(1))) {
140
+ if (normalizedPattern.startsWith('*.') && normalizedPath.endsWith(normalizedPattern.substring(1))) {
133
141
  return true;
134
142
  }
135
143
  }