abapgit-agent 1.15.3 → 1.16.1

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.
@@ -48,6 +48,24 @@ Commands:
48
48
  unit --files <file1>,<file2>,...
49
49
  Run AUnit tests for ABAP test class files (.testclasses.abap)
50
50
 
51
+ run --program <NAME> | --class <NAME>
52
+ Execute an ABAP program or class (IF_OO_ADT_CLASSRUN) and display its output.
53
+
54
+ drop --files <file> [--pull] [--transport <TRANSPORT>] [--conflict-mode <mode>]
55
+ Physically delete a single ABAP object from the ABAP system.
56
+ Use --pull to immediately re-activate from git after deletion.
57
+
58
+ lint [--files <file1,...>] [--base <branch>] [--config <file>]
59
+ Run abaplint static analysis on changed ABAP files. Requires .abaplint.json.
60
+
61
+ debug <subcommand> [options]
62
+ Manage ABAP debugger breakpoints and attach debug sessions.
63
+ Subcommands: set, list, delete, attach, step, vars, stack
64
+
65
+ transport <subcommand> [options]
66
+ List and manage SAP transport requests.
67
+ Subcommands: list, create, release
68
+
51
69
  tree --package <package> [--depth <n>] [--include-types] [--json]
52
70
  Display package hierarchy tree from ABAP system
53
71
 
@@ -57,6 +75,9 @@ Commands:
57
75
  view --objects <obj1>,<obj2>,... [--type <type>] [--json]
58
76
  View ABAP object definitions from the ABAP system
59
77
 
78
+ preview --objects <obj1>,... [--type <type>] [--limit <n>] [--where <cond>] [--json]
79
+ Preview data from ABAP tables or CDS views
80
+
60
81
  where --objects <obj1>,<obj2>,... [--type <type>] [--limit <n>] [--json]
61
82
  Find where-used list for ABAP objects (classes, interfaces, programs)
62
83
 
@@ -93,6 +114,9 @@ Commands:
93
114
  - Use --dry-run to preview changes without applying them
94
115
  - Use --yes to skip confirmation prompt
95
116
 
117
+ upgrade [--abap-only] [--cli-only] [--version <v>]
118
+ Upgrade CLI and/or ABAP backend to latest or specific version.
119
+
96
120
  health
97
121
  Check if ABAP REST API is healthy
98
122
 
@@ -114,9 +138,14 @@ Examples:
114
138
  abapgit-agent syntax --files src/zcl_my_class.clas.abap # Check without pull
115
139
  abapgit-agent syntax --files src/zmy_prog.prog.abap --cloud # ABAP Cloud check
116
140
  abapgit-agent unit --files src/zcl_my_test.clas.testclasses.abap # Run unit tests
117
- abapgit-agent tree --package $MY_PACKAGE # Display package tree
141
+ abapgit-agent run --program ZMY_REPORT # Execute report
142
+ abapgit-agent run --class ZCL_MY_RUNNER # Execute class
143
+ abapgit-agent drop --files src/zcl_foo.clas.abap --pull # Drop and re-activate
144
+ abapgit-agent lint # abaplint on changed files
145
+ abapgit-agent tree --package $MY_PACKAGE # Display package tree
118
146
  abapgit-agent list --package $MY_PACKAGE --type CLAS,INTF # List classes & interfaces
119
147
  abapgit-agent view --objects ZCL_MY_CLASS # View class definition
148
+ abapgit-agent preview --objects SFLIGHT # Preview table data
120
149
  abapgit-agent where --objects ZCL_MY_CLASS # Find where class is used
121
150
  abapgit-agent dump --date TODAY # Recent short dumps
122
151
  abapgit-agent dump --user DEVELOPER --detail 1 # Full detail of first result
@@ -127,6 +156,8 @@ Examples:
127
156
  abapgit-agent health # Health check
128
157
  abapgit-agent status # Configuration status
129
158
 
159
+ Run "abapgit-agent <command> --help" for detailed usage of any command.
160
+
130
161
  For more info: https://github.com/SylvosCai/abapgit-agent
131
162
  `);
132
163
  }
@@ -30,5 +30,6 @@ module.exports = {
30
30
  pull: require('./pull'),
31
31
  upgrade: require('./upgrade'),
32
32
  transport: require('./transport'),
33
- lint: require('./lint')
33
+ lint: require('./lint'),
34
+ drop: require('./drop')
34
35
  };
@@ -250,6 +250,29 @@ module.exports = {
250
250
  async execute(args, context) {
251
251
  const { loadConfig, AbapHttp } = context;
252
252
 
253
+ if (args.includes('--help') || args.includes('-h')) {
254
+ console.log(`
255
+ Usage:
256
+ abapgit-agent inspect --files <file1>,<file2>,... [--variant <check-variant>] [--junit-output <file>] [--json]
257
+
258
+ Description:
259
+ Run SAP Code Inspector checks on activated ABAP objects. Requires the objects
260
+ to be already active in the ABAP system (run pull first).
261
+
262
+ Parameters:
263
+ --files <file1,...> Comma-separated ABAP source files (required).
264
+ --variant <variant> Code Inspector variant (default: system default).
265
+ --junit-output <file> Write results as JUnit XML to this file.
266
+ --json Output as JSON.
267
+
268
+ Examples:
269
+ abapgit-agent inspect --files src/zcl_my_class.clas.abap
270
+ abapgit-agent inspect --files src/zcl_my_class.clas.abap --variant ALL_CHECKS
271
+ abapgit-agent inspect --files src/zcl_my_class.clas.abap --junit-output reports/inspect.xml
272
+ `);
273
+ return;
274
+ }
275
+
253
276
  const jsonOutput = args.includes('--json');
254
277
  const verbose = args.includes('--verbose');
255
278
  const filesArgIndex = args.indexOf('--files');
@@ -24,6 +24,32 @@ module.exports = {
24
24
  requiresAbapConfig: false,
25
25
 
26
26
  execute(args) {
27
+ if (args.includes('--help') || args.includes('-h')) {
28
+ console.log(`
29
+ Usage:
30
+ abapgit-agent lint [--files <file1,...>] [--base <branch>] [--config <file>]
31
+ [--outformat <format>] [--outfile <file>]
32
+
33
+ Description:
34
+ Run abaplint static analysis on changed ABAP files. Requires .abaplint.json in repo root.
35
+ By default detects files changed vs HEAD~1 (or vs --base branch).
36
+
37
+ Parameters:
38
+ --files <file1,...> Check specific files instead of auto-detecting changed files.
39
+ --base <branch> Diff against this branch instead of HEAD~1 (e.g. main).
40
+ --config <file> abaplint config file (default: .abaplint.json).
41
+ --outformat <format> Output format: checkstyle (default: text).
42
+ --outfile <file> Write output to file instead of stdout.
43
+
44
+ Examples:
45
+ abapgit-agent lint
46
+ abapgit-agent lint --base main
47
+ abapgit-agent lint --files src/zcl_foo.clas.abap
48
+ abapgit-agent lint --outformat checkstyle --outfile reports/abaplint.xml
49
+ `);
50
+ return;
51
+ }
52
+
27
53
  const configPath = argValue(args, '--config') || '.abaplint.json';
28
54
  const baseBranch = argValue(args, '--base');
29
55
  const filesArg = argValue(args, '--files');
@@ -11,6 +11,31 @@ module.exports = {
11
11
  async execute(args, context) {
12
12
  const { loadConfig, AbapHttp } = context;
13
13
 
14
+ if (args.includes('--help') || args.includes('-h')) {
15
+ console.log(`
16
+ Usage:
17
+ abapgit-agent list --package <package> [--type <types>] [--name <pattern>] [--limit <n>] [--offset <n>] [--json]
18
+
19
+ Description:
20
+ List ABAP objects in a package with optional filtering and pagination.
21
+
22
+ Parameters:
23
+ --package <package> Package to list (required). Enclose $-packages in quotes.
24
+ --type <types> Comma-separated object types to filter (e.g. CLAS,INTF).
25
+ --name <pattern> Filter by object name pattern (e.g. ZCL_MY*).
26
+ --limit <n> Maximum number of results (default: 100).
27
+ --offset <n> Skip first N results (for pagination).
28
+ --json Output as JSON.
29
+
30
+ Examples:
31
+ abapgit-agent list --package ZMY_PACKAGE
32
+ abapgit-agent list --package ZMY_PACKAGE --type CLAS,INTF
33
+ abapgit-agent list --package ZMY_PACKAGE --name ZCL_MY*
34
+ abapgit-agent list --package ZMY_PACKAGE --limit 20 --offset 40
35
+ `);
36
+ return;
37
+ }
38
+
14
39
  const packageArgIndex = args.indexOf('--package');
15
40
  if (packageArgIndex === -1) {
16
41
  console.error('Error: --package parameter required');
@@ -11,6 +11,36 @@ module.exports = {
11
11
  async execute(args, context) {
12
12
  const { loadConfig, AbapHttp, validators } = context;
13
13
 
14
+ if (args.includes('--help') || args.includes('-h')) {
15
+ console.log(`
16
+ Usage:
17
+ abapgit-agent preview --objects <obj1>,... [--type <type>] [--limit <n>] [--offset <n>]
18
+ [--where <condition>] [--columns <cols>] [--vertical] [--compact] [--json]
19
+
20
+ Description:
21
+ Preview data from ABAP tables or CDS views.
22
+
23
+ Parameters:
24
+ --objects <obj1,...> Comma-separated table/view names (required).
25
+ --type <type> Object type: TABL, DDLS (auto-detected if omitted).
26
+ --limit <n> Maximum number of rows (default: 20).
27
+ --offset <n> Skip first N rows (for pagination).
28
+ --where <condition> WHERE clause filter (e.g. "CARRID = 'AA'").
29
+ --columns <cols> Comma-separated column names to display.
30
+ --vertical Display each row vertically (field: value).
31
+ --compact Compact output (no borders).
32
+ --json Output as JSON.
33
+
34
+ Examples:
35
+ abapgit-agent preview --objects SFLIGHT
36
+ abapgit-agent preview --objects SFLIGHT --limit 5
37
+ abapgit-agent preview --objects SFLIGHT --where "CARRID = 'AA'"
38
+ abapgit-agent preview --objects ZC_MY_VIEW --type DDLS
39
+ abapgit-agent preview --objects SFLIGHT --offset 10 --limit 20
40
+ `);
41
+ return;
42
+ }
43
+
14
44
  const objectsArgIndex = args.indexOf('--objects');
15
45
  if (objectsArgIndex === -1 || objectsArgIndex + 1 >= args.length) {
16
46
  console.error('Error: --objects parameter required');
@@ -42,6 +42,38 @@ module.exports = {
42
42
 
43
43
  async execute(args, context) {
44
44
  const { loadConfig, AbapHttp, gitUtils, getTransport, getSafeguards, getConflictSettings, getTransportSettings } = context;
45
+
46
+ if (args.includes('--help') || args.includes('-h')) {
47
+ console.log(`
48
+ Usage:
49
+ abapgit-agent pull [--url <git-url>] [--branch <branch>] [--files <file1,file2,...>]
50
+ [--transport <TRANSPORT>] [--conflict-mode <mode>] [--sync-xml]
51
+
52
+ Description:
53
+ Pull and activate ABAP objects from a git repository into the ABAP system.
54
+ Auto-detects git remote URL and branch from the current directory.
55
+
56
+ Parameters:
57
+ --url <git-url> Git repository URL. Auto-detected from git remote if omitted.
58
+ --branch <branch> Branch to pull from. Auto-detected from current branch if omitted.
59
+ --files <file1,...> Comma-separated list of files to pull (selective activation).
60
+ --transport <TRANSPORT> Transport request (e.g. DEVK900001).
61
+ --conflict-mode <mode> Conflict handling: abort (default) or ignore.
62
+ --sync-xml Rewrite XML metadata files to match ABAP serializer output.
63
+ --verbose Show detailed activation output.
64
+
65
+ Examples:
66
+ abapgit-agent pull
67
+ abapgit-agent pull --branch develop
68
+ abapgit-agent pull --files src/zcl_my_class.clas.abap
69
+ abapgit-agent pull --files src/zcl_foo.clas.abap,src/zif_foo.intf.abap
70
+ abapgit-agent pull --transport DEVK900001
71
+ abapgit-agent pull --conflict-mode ignore
72
+ abapgit-agent pull --files src/zcl_foo.clas.abap --sync-xml
73
+ `);
74
+ return;
75
+ }
76
+
45
77
  const verbose = args.includes('--verbose');
46
78
  const syncXml = args.includes('--sync-xml');
47
79
 
@@ -33,6 +33,27 @@ module.exports = {
33
33
  async execute(args, context) {
34
34
  const { loadConfig, getSafeguards } = context;
35
35
 
36
+ if (args.includes('--help') || args.includes('-h')) {
37
+ console.log(`
38
+ Usage:
39
+ abapgit-agent run --program <NAME>
40
+ abapgit-agent run --class <NAME>
41
+
42
+ Description:
43
+ Execute an ABAP program or a class implementing IF_OO_ADT_CLASSRUN and display its output.
44
+
45
+ Parameters:
46
+ --program <NAME> Execute an ABAP report/program.
47
+ --class <NAME> Execute a class implementing IF_OO_ADT_CLASSRUN (run method).
48
+ --json Output as JSON.
49
+
50
+ Examples:
51
+ abapgit-agent run --program ZMY_REPORT
52
+ abapgit-agent run --class ZCL_MY_RUNNER
53
+ `);
54
+ return;
55
+ }
56
+
36
57
  // Check project-level safeguards
37
58
  const safeguards = getSafeguards();
38
59
  if (safeguards.disableRun) {
@@ -13,6 +13,19 @@ module.exports = {
13
13
  async execute(args, context) {
14
14
  const { gitUtils, isAbapIntegrationEnabled, AbapHttp, loadConfig } = context;
15
15
 
16
+ if (args.includes('--help') || args.includes('-h')) {
17
+ console.log(`
18
+ Usage:
19
+ abapgit-agent status
20
+
21
+ Description:
22
+ Check whether ABAP integration is configured for the current repository.
23
+ Shows the config location, SAP host, and whether the abapGit online repository
24
+ is registered in the ABAP system.
25
+ `);
26
+ return;
27
+ }
28
+
16
29
  if (isAbapIntegrationEnabled()) {
17
30
  console.log('✅ ABAP Git Agent is ENABLED');
18
31
  console.log(' Config location:', pathModule.join(process.cwd(), '.abapGitAgent'));
@@ -14,6 +14,28 @@ module.exports = {
14
14
  async execute(args, context) {
15
15
  const { loadConfig, AbapHttp } = context;
16
16
 
17
+ if (args.includes('--help') || args.includes('-h')) {
18
+ console.log(`
19
+ Usage:
20
+ abapgit-agent syntax --files <file1>,<file2>,... [--cloud] [--json]
21
+
22
+ Description:
23
+ Check syntax of local ABAP source files WITHOUT pulling or activating them.
24
+ Reads source from local files and checks directly in the ABAP system.
25
+
26
+ Parameters:
27
+ --files <file1,...> Comma-separated ABAP source files (required). Accepts CLAS, INTF, PROG.
28
+ --cloud Use ABAP Cloud (BTP) stricter syntax check.
29
+ --json Output as JSON.
30
+
31
+ Examples:
32
+ abapgit-agent syntax --files src/zcl_my_class.clas.abap
33
+ abapgit-agent syntax --files src/zcl_foo.clas.abap,src/zif_foo.intf.abap
34
+ abapgit-agent syntax --files src/zmy_prog.prog.abap --cloud
35
+ `);
36
+ return;
37
+ }
38
+
17
39
  const filesArgIndex = args.indexOf('--files');
18
40
  if (filesArgIndex === -1 || filesArgIndex + 1 >= args.length) {
19
41
  console.error('Error: --files parameter required');
@@ -48,6 +70,7 @@ module.exports = {
48
70
  // Build objects array from files
49
71
  // Group class files together (main + locals)
50
72
  const classFilesMap = new Map(); // className -> { main, locals_def, locals_imp }
73
+ const fugrGroupMap = new Map(); // groupName -> { dir, fmFiles: Map<fmName, source> }
51
74
  const objects = [];
52
75
 
53
76
  for (const file of syntaxFiles) {
@@ -83,6 +106,35 @@ module.exports = {
83
106
  objType = 'DDLS';
84
107
  objName = baseName.split('.')[0].toUpperCase();
85
108
  fileKind = 'main';
109
+ } else if (baseName.includes('.fugr.')) {
110
+ objType = 'FUGR';
111
+ const parts = baseName.split('.'); // e.g. ['zmy_fugr', 'fugr', 'zmy_my_function', 'abap']
112
+ objName = parts[0].toUpperCase(); // group name e.g. 'ZMY_FUGR'
113
+ const includeFile = parts[2] || ''; // e.g. 'zmy_my_function', 'lzmy_fugrtop', 'saplzmy_fugr'
114
+ const groupLower = parts[0].toLowerCase();
115
+ const isTopInclude = new RegExp(`^l${groupLower}top$`, 'i').test(includeFile);
116
+ const isUInclude = new RegExp(`^l${groupLower}u\\d+$`, 'i').test(includeFile);
117
+ const isSapl = includeFile.toLowerCase().startsWith('sapl');
118
+ const isFm = !isTopInclude && !isUInclude && !isSapl && includeFile !== '';
119
+
120
+ // Read source and store in fugrGroupMap
121
+ const filePath = pathModule.resolve(file);
122
+ if (!fs.existsSync(filePath)) {
123
+ console.error(` Error: File not found: ${file}`);
124
+ continue;
125
+ }
126
+ const source = fs.readFileSync(filePath, 'utf8');
127
+ const dir = pathModule.dirname(filePath);
128
+
129
+ if (!fugrGroupMap.has(objName)) {
130
+ fugrGroupMap.set(objName, { dir, fmFiles: new Map() });
131
+ }
132
+ if (isFm) {
133
+ const fmName = includeFile.toUpperCase();
134
+ fugrGroupMap.get(objName).fmFiles.set(fmName, source);
135
+ }
136
+ // Skip adding to objects here — handled after auto-detection below
137
+ continue;
86
138
  }
87
139
 
88
140
  // Read source from file
@@ -236,12 +288,74 @@ module.exports = {
236
288
  }
237
289
  }
238
290
 
291
+ // Helper: read FIXPT from SAPL XML for a function group
292
+ function readFugrFixpt(dir, groupName) {
293
+ const xmlFile = pathModule.join(dir, `${groupName.toLowerCase()}.fugr.sapl${groupName.toLowerCase()}.xml`);
294
+ if (fs.existsSync(xmlFile)) {
295
+ const xmlContent = fs.readFileSync(xmlFile, 'utf8');
296
+ const fixptMatch = xmlContent.match(/<FIXPT>([^<]+)<\/FIXPT>/);
297
+ if (fixptMatch && fixptMatch[1] === 'X') return 'X';
298
+ }
299
+ return '';
300
+ }
301
+
302
+ // Helper: classify a FUGR include filename — returns fm name (uppercase) or null if not an FM file
303
+ function getFugrFmName(includeFile, groupLower) {
304
+ if (!includeFile) return null;
305
+ const isTopInclude = new RegExp(`^l${groupLower}top$`, 'i').test(includeFile);
306
+ const isUInclude = new RegExp(`^l${groupLower}u\\d+$`, 'i').test(includeFile);
307
+ const isSapl = includeFile.toLowerCase().startsWith('sapl');
308
+ if (isTopInclude || isUInclude || isSapl) return null;
309
+ return includeFile.toUpperCase();
310
+ }
311
+
312
+ // Auto-detect all FM files for each function group and build objects
313
+ for (const [groupName, groupData] of fugrGroupMap) {
314
+ const { dir } = groupData;
315
+ const groupLower = groupName.toLowerCase();
316
+ const prefix = `${groupLower}.fugr.`;
317
+
318
+ // Scan directory for all FUGR files belonging to this group
319
+ let allFiles;
320
+ try {
321
+ allFiles = fs.readdirSync(dir);
322
+ } catch (e) {
323
+ allFiles = [];
324
+ }
325
+ for (const f of allFiles) {
326
+ if (!f.toLowerCase().startsWith(prefix) || !f.toLowerCase().endsWith('.abap')) continue;
327
+ const parts = f.split('.');
328
+ const includeFile = parts[2] || '';
329
+ const fmName = getFugrFmName(includeFile, groupLower);
330
+ if (fmName && !groupData.fmFiles.has(fmName)) {
331
+ groupData.fmFiles.set(fmName, fs.readFileSync(pathModule.join(dir, f), 'utf8'));
332
+ if (!jsonOutput) console.log(` Auto-detected: ${f}`);
333
+ }
334
+ }
335
+
336
+ if (groupData.fmFiles.size === 0) {
337
+ if (!jsonOutput) console.error(` Warning: No FM source files found for FUGR ${groupName}`);
338
+ continue;
339
+ }
340
+
341
+ const fixpt = readFugrFixpt(dir, groupName);
342
+
343
+ // Add one object per FM
344
+ for (const [fmName, source] of groupData.fmFiles) {
345
+ objects.push({
346
+ type: 'FUGR',
347
+ name: groupName,
348
+ source: source,
349
+ fugr_include_name: fmName,
350
+ fixpt: fixpt
351
+ });
352
+ }
353
+ }
354
+
239
355
  if (objects.length === 0) {
240
356
  console.error(' No valid files to check');
241
357
  process.exit(1);
242
358
  }
243
-
244
- // Send request
245
359
  const data = {
246
360
  objects: objects,
247
361
  uccheck: cloudMode ? '5' : 'X'
@@ -258,7 +372,8 @@ module.exports = {
258
372
  console.log(JSON.stringify(result, null, 2));
259
373
  } else {
260
374
  // Display results for each object
261
- for (const res of results) {
375
+ for (let i = 0; i < results.length; i++) {
376
+ const res = results[i];
262
377
  const objSuccess = res.SUCCESS !== undefined ? res.SUCCESS : res.success;
263
378
  const objType = res.OBJECT_TYPE || res.object_type || 'UNKNOWN';
264
379
  const objName = res.OBJECT_NAME || res.object_name || 'UNKNOWN';
@@ -267,13 +382,18 @@ module.exports = {
267
382
  const warnings = res.WARNINGS || res.warnings || [];
268
383
  const objMessage = res.MESSAGE || res.message || '';
269
384
 
385
+ // For FUGR: show which FM was checked alongside the group name
386
+ const sentObj = objects[i] || {};
387
+ const fugrFmLabel = (objType === 'FUGR' && sentObj.fugr_include_name)
388
+ ? ` (${sentObj.fugr_include_name})` : '';
389
+
270
390
  if (objSuccess) {
271
- console.log(`✅ ${objType} ${objName} - Syntax check passed`);
391
+ console.log(`✅ ${objType} ${objName}${fugrFmLabel} - Syntax check passed`);
272
392
  if (warnings.length > 0) {
273
393
  console.log(` (${warnings.length} warning(s))`);
274
394
  }
275
395
  } else {
276
- console.log(`❌ ${objType} ${objName} - Syntax check failed (${errorCount} error(s))`);
396
+ console.log(`❌ ${objType} ${objName}${fugrFmLabel} - Syntax check failed (${errorCount} error(s))`);
277
397
  console.log('');
278
398
  console.log('Errors:');
279
399
  console.log('─'.repeat(60));
@@ -287,19 +407,25 @@ module.exports = {
287
407
 
288
408
  // Display which file/include the error is in
289
409
  if (include) {
290
- const includeMap = {
291
- 'main': { display: 'Main class', suffix: '.clas.abap' },
292
- 'locals_def': { display: 'Local definitions', suffix: '.clas.locals_def.abap' },
293
- 'locals_imp': { display: 'Local implementations', suffix: '.clas.locals_imp.abap' },
294
- 'testclasses': { display: 'Test classes', suffix: '.clas.testclasses.abap' }
295
- };
296
- const includeInfo = includeMap[include] || { display: include, suffix: '' };
297
-
298
- // Show both display name and filename
299
- if (includeInfo.suffix) {
300
- console.log(` In: ${includeInfo.display} (${objName.toLowerCase()}${includeInfo.suffix})`);
410
+ // For FUGR: include = lowercase FM name → display as '<group>.fugr.<fm_name>.abap'
411
+ if (objType === 'FUGR') {
412
+ const fugrFile = `${objName.toLowerCase()}.fugr.${include}.abap`;
413
+ console.log(` In: Function module ${include.toUpperCase()} (${fugrFile})`);
301
414
  } else {
302
- console.log(` In: ${includeInfo.display}`);
415
+ const includeMap = {
416
+ 'main': { display: 'Main class', suffix: '.clas.abap' },
417
+ 'locals_def': { display: 'Local definitions', suffix: '.clas.locals_def.abap' },
418
+ 'locals_imp': { display: 'Local implementations', suffix: '.clas.locals_imp.abap' },
419
+ 'testclasses': { display: 'Test classes', suffix: '.clas.testclasses.abap' }
420
+ };
421
+ const includeInfo = includeMap[include] || { display: include, suffix: '' };
422
+
423
+ // Show both display name and filename
424
+ if (includeInfo.suffix) {
425
+ console.log(` In: ${includeInfo.display} (${objName.toLowerCase()}${includeInfo.suffix})`);
426
+ } else {
427
+ console.log(` In: ${includeInfo.display}`);
428
+ }
303
429
  }
304
430
  }
305
431
  if (methodName) {
@@ -148,6 +148,28 @@ module.exports = {
148
148
  async execute(args, context) {
149
149
  const { loadConfig, AbapHttp } = context;
150
150
 
151
+ if (args.includes('--help') || args.includes('-h')) {
152
+ console.log(`
153
+ Usage:
154
+ abapgit-agent tree --package <package> [--depth <n>] [--include-types] [--json]
155
+
156
+ Description:
157
+ Display the package hierarchy tree from the ABAP system.
158
+
159
+ Parameters:
160
+ --package <package> Root package to display (required). Enclose $-packages in quotes.
161
+ --depth <n> Maximum depth to traverse (default: unlimited).
162
+ --include-types Show object type counts per package.
163
+ --json Output as JSON.
164
+
165
+ Examples:
166
+ abapgit-agent tree --package ZMY_PACKAGE
167
+ abapgit-agent tree --package '$MY_LOCAL_PKG'
168
+ abapgit-agent tree --package ZMY_PACKAGE --depth 2 --include-types
169
+ `);
170
+ return;
171
+ }
172
+
151
173
  const packageArgIndex = args.indexOf('--package');
152
174
  if (packageArgIndex === -1) {
153
175
  console.error('Error: --package parameter required');
@@ -232,6 +232,29 @@ module.exports = {
232
232
  async execute(args, context) {
233
233
  const { loadConfig, AbapHttp } = context;
234
234
 
235
+ if (args.includes('--help') || args.includes('-h')) {
236
+ console.log(`
237
+ Usage:
238
+ abapgit-agent unit --files <file1>,<file2>,... [--coverage] [--junit-output <file>] [--json]
239
+
240
+ Description:
241
+ Run AUnit tests for ABAP test class files (.testclasses.abap).
242
+ Objects must be already active in the ABAP system (run pull first).
243
+
244
+ Parameters:
245
+ --files <file1,...> Comma-separated .testclasses.abap files (required).
246
+ --coverage Include code coverage data in output.
247
+ --junit-output <file> Write results as JUnit XML to this file.
248
+ --json Output as JSON.
249
+
250
+ Examples:
251
+ abapgit-agent unit --files src/zcl_my_test.clas.testclasses.abap
252
+ abapgit-agent unit --files src/zcl_my_test.clas.testclasses.abap --coverage
253
+ abapgit-agent unit --files src/zcl_my_test.clas.testclasses.abap --junit-output reports/unit.xml
254
+ `);
255
+ return;
256
+ }
257
+
235
258
  const jsonOutput = args.includes('--json');
236
259
  const verbose = args.includes('--verbose');
237
260
  const filesArgIndex = args.indexOf('--files');
@@ -14,6 +14,34 @@ module.exports = {
14
14
  async execute(args, context) {
15
15
  const { versionCheck, loadConfig, isAbapIntegrationEnabled } = context;
16
16
 
17
+ if (args.includes('--help') || args.includes('-h')) {
18
+ console.log(`
19
+ Usage:
20
+ abapgit-agent upgrade [--abap-only] [--cli-only] [--version <v>] [--check] [--yes]
21
+
22
+ Description:
23
+ Upgrade the abapgit-agent CLI (npm package) and/or the ABAP backend to the latest
24
+ or a specific version.
25
+
26
+ Parameters:
27
+ --abap-only Upgrade only the ABAP backend (skip CLI npm upgrade).
28
+ --cli-only Upgrade only the CLI npm package (skip ABAP backend).
29
+ --version <v> Upgrade to a specific version (e.g. 1.15.0).
30
+ --check Check for available upgrades without installing.
31
+ --transport <T> Transport request for ABAP backend upgrade.
32
+ --yes, -y Skip confirmation prompt.
33
+ --dry-run Show what would be done without making changes.
34
+
35
+ Examples:
36
+ abapgit-agent upgrade
37
+ abapgit-agent upgrade --check
38
+ abapgit-agent upgrade --cli-only
39
+ abapgit-agent upgrade --abap-only --transport DEVK900001
40
+ abapgit-agent upgrade --version 1.15.0
41
+ `);
42
+ return;
43
+ }
44
+
17
45
  // Parse flags
18
46
  const flags = this.parseFlags(args);
19
47
 
@@ -193,6 +193,35 @@ module.exports = {
193
193
  async execute(args, context) {
194
194
  const { loadConfig, AbapHttp } = context;
195
195
 
196
+ if (args.includes('--help') || args.includes('-h')) {
197
+ console.log(`
198
+ Usage:
199
+ abapgit-agent view --objects <obj1>,<obj2>,... [--type <type>] [--full] [--lines] [--json]
200
+ abapgit-agent view --objects <FUGR> --type FUGR [--full] [--fm <name>] [--lines]
201
+
202
+ Description:
203
+ View ABAP object definitions from the ABAP system.
204
+
205
+ Parameters:
206
+ --objects <obj1,...> Comma-separated object names (required).
207
+ --type <type> Object type: CLAS, INTF, PROG, TABL, STRU, DTEL, TTYP, DOMA,
208
+ DDLS, DCLS, MSAG, FUGR (auto-detected from TADIR if omitted).
209
+ --full Show full source including all method implementations.
210
+ --lines Show dual line numbers (G = global for debug set, [N] = include-local).
211
+ --fm <name> With --full: show only the specified function module (FUGR only).
212
+ --json Output as JSON.
213
+
214
+ Examples:
215
+ abapgit-agent view --objects ZCL_MY_CLASS
216
+ abapgit-agent view --objects ZCL_MY_CLASS --full
217
+ abapgit-agent view --objects ZCL_MY_CLASS --full --lines
218
+ abapgit-agent view --objects ZMY_TABLE --type TABL
219
+ abapgit-agent view --objects SUSR --type FUGR --full --fm AUTHORITY_CHECK --lines
220
+ abapgit-agent view --objects ZCL_FOO,ZIF_BAR
221
+ `);
222
+ return;
223
+ }
224
+
196
225
  const objectsArgIndex = args.indexOf('--objects');
197
226
  if (objectsArgIndex === -1 || objectsArgIndex + 1 >= args.length) {
198
227
  console.error('Error: --objects parameter required');