abapgit-agent 1.7.1 ā 1.8.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/.abapGitAgent.example +11 -0
- package/README.md +7 -7
- package/abap/.github/copilot-instructions.md +254 -0
- package/abap/CLAUDE.md +432 -0
- package/abap/guidelines/00_index.md +8 -0
- package/abap/guidelines/01_sql.md +8 -0
- package/abap/guidelines/02_exceptions.md +8 -0
- package/abap/guidelines/03_testing.md +8 -0
- package/abap/guidelines/04_cds.md +8 -0
- package/abap/guidelines/05_classes.md +8 -0
- package/abap/guidelines/06_objects.md +8 -0
- package/abap/guidelines/07_json.md +8 -0
- package/abap/guidelines/08_abapgit.md +8 -0
- package/abap/guidelines/09_unit_testable_code.md +8 -0
- package/bin/abapgit-agent +61 -2789
- package/package.json +25 -5
- package/src/agent.js +213 -20
- package/src/commands/create.js +102 -0
- package/src/commands/delete.js +72 -0
- package/src/commands/health.js +24 -0
- package/src/commands/help.js +111 -0
- package/src/commands/import.js +99 -0
- package/src/commands/init.js +321 -0
- package/src/commands/inspect.js +184 -0
- package/src/commands/list.js +143 -0
- package/src/commands/preview.js +277 -0
- package/src/commands/pull.js +278 -0
- package/src/commands/ref.js +96 -0
- package/src/commands/status.js +52 -0
- package/src/commands/syntax.js +290 -0
- package/src/commands/tree.js +209 -0
- package/src/commands/unit.js +133 -0
- package/src/commands/view.js +215 -0
- package/src/commands/where.js +138 -0
- package/src/config.js +11 -1
- package/src/utils/abap-http.js +347 -0
- package/src/{ref-search.js ā utils/abap-reference.js} +119 -1
- package/src/utils/git-utils.js +58 -0
- package/src/utils/validators.js +72 -0
- package/src/utils/version-check.js +80 -0
- package/src/abap-client.js +0 -523
|
@@ -0,0 +1,278 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pull command - Pull and activate ABAP objects from git repository
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
module.exports = {
|
|
6
|
+
name: 'pull',
|
|
7
|
+
description: 'Pull and activate ABAP objects from git repository',
|
|
8
|
+
requiresAbapConfig: true,
|
|
9
|
+
requiresVersionCheck: true,
|
|
10
|
+
|
|
11
|
+
async execute(args, context) {
|
|
12
|
+
const { loadConfig, AbapHttp, gitUtils, getTransport } = context;
|
|
13
|
+
|
|
14
|
+
const urlArgIndex = args.indexOf('--url');
|
|
15
|
+
const branchArgIndex = args.indexOf('--branch');
|
|
16
|
+
const filesArgIndex = args.indexOf('--files');
|
|
17
|
+
const transportArgIndex = args.indexOf('--transport');
|
|
18
|
+
|
|
19
|
+
// Auto-detect git remote URL if not provided
|
|
20
|
+
let gitUrl = urlArgIndex !== -1 ? args[urlArgIndex + 1] : null;
|
|
21
|
+
let branch = branchArgIndex !== -1 ? args[branchArgIndex + 1] : gitUtils.getBranch();
|
|
22
|
+
let files = null;
|
|
23
|
+
|
|
24
|
+
// Transport: CLI arg takes priority, then config/environment, then null
|
|
25
|
+
let transportRequest = null;
|
|
26
|
+
if (transportArgIndex !== -1 && transportArgIndex + 1 < args.length) {
|
|
27
|
+
// Explicit --transport argument
|
|
28
|
+
transportRequest = args[transportArgIndex + 1];
|
|
29
|
+
} else {
|
|
30
|
+
// Fall back to config or environment variable
|
|
31
|
+
transportRequest = getTransport();
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
if (filesArgIndex !== -1 && filesArgIndex + 1 < args.length) {
|
|
35
|
+
files = args[filesArgIndex + 1].split(',').map(f => f.trim());
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
if (!gitUrl) {
|
|
39
|
+
gitUrl = gitUtils.getRemoteUrl();
|
|
40
|
+
if (!gitUrl) {
|
|
41
|
+
console.error('Error: Not in a git repository or no remote configured.');
|
|
42
|
+
console.error('Either run from a git repo, or specify --url <git-url>');
|
|
43
|
+
process.exit(1);
|
|
44
|
+
}
|
|
45
|
+
console.log(`š Auto-detected git remote: ${gitUrl}`);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
await this.pull(gitUrl, branch, files, transportRequest, loadConfig, AbapHttp);
|
|
49
|
+
},
|
|
50
|
+
|
|
51
|
+
async pull(gitUrl, branch = 'main', files = null, transportRequest = null, loadConfig, AbapHttp) {
|
|
52
|
+
const TERM_WIDTH = process.stdout.columns || 80;
|
|
53
|
+
|
|
54
|
+
console.log(`\nš Starting pull for: ${gitUrl}`);
|
|
55
|
+
console.log(` Branch: ${branch}`);
|
|
56
|
+
if (files && files.length > 0) {
|
|
57
|
+
console.log(` Files: ${files.join(', ')}`);
|
|
58
|
+
}
|
|
59
|
+
if (transportRequest) {
|
|
60
|
+
console.log(` Transport Request: ${transportRequest}`);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
try {
|
|
64
|
+
const config = loadConfig();
|
|
65
|
+
|
|
66
|
+
// Fetch CSRF token first
|
|
67
|
+
const http = new AbapHttp(config);
|
|
68
|
+
const csrfToken = await http.fetchCsrfToken();
|
|
69
|
+
|
|
70
|
+
// Prepare request data with git credentials
|
|
71
|
+
const data = {
|
|
72
|
+
url: gitUrl,
|
|
73
|
+
branch: branch,
|
|
74
|
+
username: config.gitUsername,
|
|
75
|
+
password: config.gitPassword
|
|
76
|
+
};
|
|
77
|
+
|
|
78
|
+
// Add files array if specified
|
|
79
|
+
if (files && files.length > 0) {
|
|
80
|
+
data.files = files;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
// Add transport request if specified
|
|
84
|
+
if (transportRequest) {
|
|
85
|
+
data.transport_request = transportRequest;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
const result = await http.post('/sap/bc/z_abapgit_agent/pull', data, { csrfToken });
|
|
89
|
+
|
|
90
|
+
console.log('\n');
|
|
91
|
+
|
|
92
|
+
// Display raw result for debugging
|
|
93
|
+
if (process.env.DEBUG) {
|
|
94
|
+
console.log('Raw result:', JSON.stringify(result, null, 2));
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
// Handle uppercase keys from ABAP
|
|
98
|
+
const success = result.SUCCESS || result.success;
|
|
99
|
+
const jobId = result.JOB_ID || result.job_id;
|
|
100
|
+
const message = result.MESSAGE || result.message;
|
|
101
|
+
const errorDetail = result.ERROR_DETAIL || result.error_detail;
|
|
102
|
+
const transportRequestUsed = result.TRANSPORT_REQUEST || result.transport_request;
|
|
103
|
+
const activatedCount = result.ACTIVATED_COUNT || result.activated_count || 0;
|
|
104
|
+
const failedCount = result.FAILED_COUNT || result.failed_count || 0;
|
|
105
|
+
const logMessages = result.LOG_MESSAGES || result.log_messages || [];
|
|
106
|
+
const activatedObjects = result.ACTIVATED_OBJECTS || result.activated_objects || [];
|
|
107
|
+
const failedObjects = result.FAILED_OBJECTS || result.failed_objects || [];
|
|
108
|
+
|
|
109
|
+
// Icon mapping for message types
|
|
110
|
+
const getIcon = (type) => {
|
|
111
|
+
const icons = {
|
|
112
|
+
'S': 'ā
', // Success
|
|
113
|
+
'E': 'ā', // Error
|
|
114
|
+
'W': 'ā ļø', // Warning
|
|
115
|
+
'A': 'š' // Abort
|
|
116
|
+
};
|
|
117
|
+
return icons[type] || '';
|
|
118
|
+
};
|
|
119
|
+
|
|
120
|
+
// Calculate display width accounting for emoji (2 cells) vs ASCII (1 cell)
|
|
121
|
+
const calcWidth = (str) => {
|
|
122
|
+
if (!str) return 0;
|
|
123
|
+
let width = 0;
|
|
124
|
+
let i = 0;
|
|
125
|
+
while (i < str.length) {
|
|
126
|
+
const code = str.codePointAt(i);
|
|
127
|
+
if (!code) break;
|
|
128
|
+
// Variation selectors (FE00-FE0F) and ZWJ (200D) take 0 width
|
|
129
|
+
if (code >= 0xFE00 && code <= 0xFE0F) {
|
|
130
|
+
i += 1;
|
|
131
|
+
continue;
|
|
132
|
+
}
|
|
133
|
+
if (code === 0x200D) { // Zero width joiner
|
|
134
|
+
i += 1;
|
|
135
|
+
continue;
|
|
136
|
+
}
|
|
137
|
+
// Emoji and wide characters take 2 cells
|
|
138
|
+
if (code > 0xFFFF) {
|
|
139
|
+
width += 2;
|
|
140
|
+
i += 2; // Skip surrogate pair
|
|
141
|
+
} else if (code > 127) {
|
|
142
|
+
width += 2;
|
|
143
|
+
i += 1;
|
|
144
|
+
} else {
|
|
145
|
+
width += 1;
|
|
146
|
+
i += 1;
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
return width;
|
|
150
|
+
};
|
|
151
|
+
|
|
152
|
+
// Pad string to display width
|
|
153
|
+
const padToWidth = (str, width) => {
|
|
154
|
+
const s = str || '';
|
|
155
|
+
const currentWidth = calcWidth(s);
|
|
156
|
+
return s + ' '.repeat(Math.max(0, width - currentWidth));
|
|
157
|
+
};
|
|
158
|
+
|
|
159
|
+
if (success === 'X' || success === true) {
|
|
160
|
+
console.log(`ā
Pull completed successfully!`);
|
|
161
|
+
console.log(` Job ID: ${jobId || 'N/A'}`);
|
|
162
|
+
console.log(` Message: ${message || 'N/A'}`);
|
|
163
|
+
} else {
|
|
164
|
+
console.log(`ā Pull completed with errors!`);
|
|
165
|
+
console.log(` Job ID: ${jobId || 'N/A'}`);
|
|
166
|
+
console.log(` Message: ${message || 'N/A'}`);
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
// Display error detail if available
|
|
170
|
+
if (errorDetail && errorDetail.trim()) {
|
|
171
|
+
console.log(`\nš Error Details:`);
|
|
172
|
+
console.log('ā'.repeat(TERM_WIDTH));
|
|
173
|
+
// Handle escaped newlines from ABAP JSON
|
|
174
|
+
const formattedDetail = errorDetail.replace(/\\n/g, '\n');
|
|
175
|
+
console.log(formattedDetail);
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
// Display all messages as table (from log_messages)
|
|
179
|
+
if (logMessages && logMessages.length > 0) {
|
|
180
|
+
console.log(`\nš Pull Log (${logMessages.length} messages):`);
|
|
181
|
+
|
|
182
|
+
// Calculate column widths based on terminal width
|
|
183
|
+
const tableWidth = Math.min(TERM_WIDTH, 120);
|
|
184
|
+
const iconCol = 4; // Fixed width for icon column
|
|
185
|
+
const objCol = 28;
|
|
186
|
+
const msgCol = tableWidth - iconCol - objCol - 6; // Account for vertical lines (3 chars)
|
|
187
|
+
|
|
188
|
+
const headerLine = 'ā'.repeat(iconCol) + 'ā¼' + 'ā'.repeat(objCol) + 'ā¼' + 'ā'.repeat(msgCol);
|
|
189
|
+
const headerText = padToWidth('Icon', iconCol) + 'ā' + padToWidth('Object', objCol) + 'ā' + 'Message'.substring(0, msgCol);
|
|
190
|
+
const borderLine = 'ā'.repeat(tableWidth);
|
|
191
|
+
|
|
192
|
+
console.log(borderLine);
|
|
193
|
+
console.log(headerText);
|
|
194
|
+
console.log(headerLine);
|
|
195
|
+
|
|
196
|
+
for (const msg of logMessages) {
|
|
197
|
+
const icon = getIcon(msg.TYPE);
|
|
198
|
+
const objType = msg.OBJ_TYPE || '';
|
|
199
|
+
const objName = msg.OBJ_NAME || '';
|
|
200
|
+
const obj = objType && objName ? `${objType} ${objName}` : '';
|
|
201
|
+
const text = msg.TEXT || '';
|
|
202
|
+
|
|
203
|
+
// Truncate long text
|
|
204
|
+
const displayText = text.length > msgCol ? text.substring(0, msgCol - 3) + '...' : text;
|
|
205
|
+
|
|
206
|
+
console.log(padToWidth(icon, iconCol) + 'ā' + padToWidth(obj.substring(0, objCol), objCol) + 'ā' + displayText);
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
// Extract objects with errors from log messages (type 'E' = Error)
|
|
211
|
+
const failedObjectsFromLog = [];
|
|
212
|
+
const objectsWithErrors = new Set();
|
|
213
|
+
|
|
214
|
+
for (const msg of logMessages) {
|
|
215
|
+
if (msg.TYPE === 'E' && msg.OBJ_TYPE && msg.OBJ_NAME) {
|
|
216
|
+
const objKey = `${msg.OBJ_TYPE} ${msg.OBJ_NAME}`;
|
|
217
|
+
objectsWithErrors.add(objKey);
|
|
218
|
+
failedObjectsFromLog.push({
|
|
219
|
+
OBJ_TYPE: msg.OBJ_TYPE,
|
|
220
|
+
OBJ_NAME: msg.OBJ_NAME,
|
|
221
|
+
TEXT: msg.TEXT || 'Activation failed',
|
|
222
|
+
EXCEPTION: msg.EXCEPTION || ''
|
|
223
|
+
});
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
// Filter activated objects - only include objects without errors
|
|
228
|
+
const filteredActivatedObjects = activatedObjects.filter(obj => {
|
|
229
|
+
const objKey = obj.OBJ_TYPE && obj.OBJ_NAME ? `${obj.OBJ_TYPE} ${obj.OBJ_NAME}` : '';
|
|
230
|
+
return objKey && !objectsWithErrors.has(objKey);
|
|
231
|
+
});
|
|
232
|
+
|
|
233
|
+
// Display unique activated objects (excluding objects with errors)
|
|
234
|
+
if (filteredActivatedObjects && filteredActivatedObjects.length > 0) {
|
|
235
|
+
console.log(`\nš¦ Activated Objects (${filteredActivatedObjects.length}):`);
|
|
236
|
+
console.log('ā'.repeat(TERM_WIDTH));
|
|
237
|
+
for (const obj of filteredActivatedObjects) {
|
|
238
|
+
console.log(`ā
${obj.OBJ_TYPE} ${obj.OBJ_NAME}`);
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
// Display failed objects log (all error messages, duplicates allowed)
|
|
243
|
+
if (failedObjectsFromLog.length > 0) {
|
|
244
|
+
console.log(`\nā Failed Objects Log (${failedObjectsFromLog.length} entries):`);
|
|
245
|
+
console.log('ā'.repeat(TERM_WIDTH));
|
|
246
|
+
for (const obj of failedObjectsFromLog) {
|
|
247
|
+
const objKey = obj.OBJ_TYPE && obj.OBJ_NAME ? `${obj.OBJ_TYPE} ${obj.OBJ_NAME}` : '';
|
|
248
|
+
let text = obj.TEXT || 'Activation failed';
|
|
249
|
+
// Include exception text if available
|
|
250
|
+
if (obj.EXCEPTION && obj.EXCEPTION.trim()) {
|
|
251
|
+
text = `${text}\nException: ${obj.EXCEPTION}`;
|
|
252
|
+
}
|
|
253
|
+
console.log(`ā ${objKey}: ${text}`);
|
|
254
|
+
}
|
|
255
|
+
} else if (failedObjects && failedObjects.length > 0) {
|
|
256
|
+
// Fallback to API failed_objects if no errors in log
|
|
257
|
+
console.log(`\nā Failed Objects Log (${failedObjects.length}):`);
|
|
258
|
+
console.log('ā'.repeat(TERM_WIDTH));
|
|
259
|
+
for (const obj of failedObjects) {
|
|
260
|
+
const objKey = obj.OBJ_TYPE && obj.OBJ_NAME ? `${obj.OBJ_TYPE} ${obj.OBJ_NAME}` : '';
|
|
261
|
+
let text = obj.TEXT || 'Activation failed';
|
|
262
|
+
// Include exception text if available
|
|
263
|
+
if (obj.EXCEPTION && obj.EXCEPTION.trim()) {
|
|
264
|
+
text = `${text}\nException: ${obj.EXCEPTION}`;
|
|
265
|
+
}
|
|
266
|
+
console.log(`ā ${objKey}: ${text}`);
|
|
267
|
+
}
|
|
268
|
+
} else if (failedCount > 0) {
|
|
269
|
+
console.log(`\nā Failed Objects Log (${failedCount})`);
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
return result;
|
|
273
|
+
} catch (error) {
|
|
274
|
+
console.error(`\nā Error: ${error.message}`);
|
|
275
|
+
process.exit(1);
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
};
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Ref command - Search ABAP reference materials (cheat sheets and guidelines)
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
module.exports = {
|
|
6
|
+
name: 'ref',
|
|
7
|
+
description: 'Search ABAP reference materials',
|
|
8
|
+
requiresAbapConfig: false,
|
|
9
|
+
requiresVersionCheck: false,
|
|
10
|
+
|
|
11
|
+
async execute(args, context) {
|
|
12
|
+
const refSearch = require('../utils/abap-reference');
|
|
13
|
+
|
|
14
|
+
const topicIndex = args.indexOf('--topic');
|
|
15
|
+
const cloneIndex = args.indexOf('--clone');
|
|
16
|
+
const nameIndex = args.indexOf('--name');
|
|
17
|
+
const listTopics = args.includes('--list-topics') || args.includes('-l');
|
|
18
|
+
const listRepos = args.includes('--list-repos') || args.includes('-r');
|
|
19
|
+
const jsonOutput = args.includes('--json');
|
|
20
|
+
|
|
21
|
+
// Handle --clone option
|
|
22
|
+
if (cloneIndex !== -1 && cloneIndex + 1 < args.length) {
|
|
23
|
+
const repoUrl = args[cloneIndex + 1];
|
|
24
|
+
const name = nameIndex !== -1 && nameIndex + 1 < args.length ? args[nameIndex + 1] : null;
|
|
25
|
+
const result = refSearch.cloneRepository(repoUrl, name);
|
|
26
|
+
if (jsonOutput) {
|
|
27
|
+
console.log(JSON.stringify(result, null, 2));
|
|
28
|
+
} else {
|
|
29
|
+
refSearch.displayCloneResult(result);
|
|
30
|
+
}
|
|
31
|
+
return;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
if (listRepos) {
|
|
35
|
+
const result = await refSearch.listRepositories();
|
|
36
|
+
if (jsonOutput) {
|
|
37
|
+
console.log(JSON.stringify(result, null, 2));
|
|
38
|
+
} else {
|
|
39
|
+
refSearch.displayRepositories(result);
|
|
40
|
+
}
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
if (listTopics) {
|
|
45
|
+
const result = await refSearch.listTopics();
|
|
46
|
+
if (jsonOutput) {
|
|
47
|
+
console.log(JSON.stringify(result, null, 2));
|
|
48
|
+
} else {
|
|
49
|
+
refSearch.displayTopics(result);
|
|
50
|
+
}
|
|
51
|
+
return;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
if (topicIndex !== -1 && topicIndex + 1 < args.length) {
|
|
55
|
+
const topic = args[topicIndex + 1];
|
|
56
|
+
const result = await refSearch.getTopic(topic);
|
|
57
|
+
if (jsonOutput) {
|
|
58
|
+
console.log(JSON.stringify(result, null, 2));
|
|
59
|
+
} else {
|
|
60
|
+
refSearch.displayTopic(result);
|
|
61
|
+
}
|
|
62
|
+
return;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
// Pattern search (default)
|
|
66
|
+
const patternIndex = args.findIndex((arg, idx) => idx > 0 && !arg.startsWith('--'));
|
|
67
|
+
if (patternIndex === -1) {
|
|
68
|
+
console.error('Error: No pattern specified');
|
|
69
|
+
console.error('');
|
|
70
|
+
console.error('Usage:');
|
|
71
|
+
console.error(' abapgit-agent ref <pattern> Search for pattern');
|
|
72
|
+
console.error(' abapgit-agent ref --topic <name> View specific topic');
|
|
73
|
+
console.error(' abapgit-agent ref --list-topics List available topics');
|
|
74
|
+
console.error(' abapgit-agent ref --list-repos List reference repositories');
|
|
75
|
+
console.error(' abapgit-agent ref --clone <repo> Clone a repository');
|
|
76
|
+
console.error('');
|
|
77
|
+
console.error('Examples:');
|
|
78
|
+
console.error(' abapgit-agent ref "CORRESPONDING"');
|
|
79
|
+
console.error(' abapgit-agent ref --topic exceptions');
|
|
80
|
+
console.error(' abapgit-agent ref --list-topics');
|
|
81
|
+
console.error(' abapgit-agent ref --list-repos');
|
|
82
|
+
console.error(' abapgit-agent ref --clone SAP-samples/abap-cheat-sheets');
|
|
83
|
+
console.error(' abapgit-agent ref --clone https://github.com/abapGit/abapGit.git');
|
|
84
|
+
process.exit(1);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
const pattern = args[patternIndex];
|
|
88
|
+
const result = await refSearch.searchPattern(pattern);
|
|
89
|
+
|
|
90
|
+
if (jsonOutput) {
|
|
91
|
+
console.log(JSON.stringify(result, null, 2));
|
|
92
|
+
} else {
|
|
93
|
+
refSearch.displaySearchResults(result);
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
};
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Status command - Check if ABAP integration is configured
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
const pathModule = require('path');
|
|
6
|
+
|
|
7
|
+
module.exports = {
|
|
8
|
+
name: 'status',
|
|
9
|
+
description: 'Check if ABAP integration is configured for this repo',
|
|
10
|
+
requiresAbapConfig: false, // We check manually in execute
|
|
11
|
+
requiresVersionCheck: false,
|
|
12
|
+
|
|
13
|
+
async execute(args, context) {
|
|
14
|
+
const { gitUtils, isAbapIntegrationEnabled, AbapHttp, loadConfig } = context;
|
|
15
|
+
|
|
16
|
+
if (isAbapIntegrationEnabled()) {
|
|
17
|
+
console.log('ā
ABAP Git Agent is ENABLED');
|
|
18
|
+
console.log(' Config location:', pathModule.join(process.cwd(), '.abapGitAgent'));
|
|
19
|
+
|
|
20
|
+
// Check if repo exists in ABAP
|
|
21
|
+
const config = loadConfig();
|
|
22
|
+
const repoUrl = gitUtils.getRemoteUrl();
|
|
23
|
+
|
|
24
|
+
if (repoUrl) {
|
|
25
|
+
try {
|
|
26
|
+
const http = new AbapHttp(config);
|
|
27
|
+
const csrfToken = await http.fetchCsrfToken();
|
|
28
|
+
const result = await http.post('/sap/bc/z_abapgit_agent/status', { url: repoUrl }, { csrfToken });
|
|
29
|
+
|
|
30
|
+
const status = result.status || result.STATUS || result.SUCCESS;
|
|
31
|
+
if (status === 'Found' || status === 'X' || status === true) {
|
|
32
|
+
console.log(' Repository: ā
Created');
|
|
33
|
+
const pkg = result.package || result.PACKAGE || 'N/A';
|
|
34
|
+
const key = result.key || result.KEY || result.REPO_KEY || result.repo_key || 'N/A';
|
|
35
|
+
console.log(` Package: ${pkg}`);
|
|
36
|
+
console.log(` URL: ${repoUrl}`);
|
|
37
|
+
console.log(` Key: ${key}`);
|
|
38
|
+
} else {
|
|
39
|
+
console.log(' Repository: ā Not created');
|
|
40
|
+
console.log(' Run "abapgit-agent create" to create it');
|
|
41
|
+
}
|
|
42
|
+
} catch (error) {
|
|
43
|
+
console.log(' Repository: ā Unknown (could not check)');
|
|
44
|
+
console.log(` Error: ${error.message}`);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
} else {
|
|
48
|
+
console.log('ā ABAP Git Agent is NOT configured');
|
|
49
|
+
console.log(' Run "abapgit-agent init" to set up configuration');
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
};
|