abapgit-agent 1.1.5 → 1.2.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 (38) hide show
  1. package/.github/workflows/release.yml +9 -22
  2. package/CLAUDE.md +248 -0
  3. package/README.md +16 -2
  4. package/RELEASE_NOTES.md +80 -8
  5. package/abap/CLAUDE.md +72 -6
  6. package/abap/copilot-instructions.md +51 -0
  7. package/abap/zcl_abgagt_cmd_factory.clas.abap +2 -0
  8. package/abap/zcl_abgagt_command_tree.clas.abap +237 -0
  9. package/abap/zcl_abgagt_command_tree.clas.xml +15 -0
  10. package/abap/zcl_abgagt_command_view.clas.abap +238 -0
  11. package/abap/zcl_abgagt_command_view.clas.xml +15 -0
  12. package/abap/zcl_abgagt_resource_tree.clas.abap +70 -0
  13. package/abap/zcl_abgagt_resource_tree.clas.xml +15 -0
  14. package/abap/zcl_abgagt_resource_view.clas.abap +68 -0
  15. package/abap/zcl_abgagt_resource_view.clas.xml +15 -0
  16. package/abap/zcl_abgagt_rest_handler.clas.abap +2 -0
  17. package/abap/zcl_abgagt_viewer_clas.clas.abap +58 -0
  18. package/abap/zcl_abgagt_viewer_clas.clas.xml +15 -0
  19. package/abap/zcl_abgagt_viewer_dtel.clas.abap +98 -0
  20. package/abap/zcl_abgagt_viewer_dtel.clas.xml +15 -0
  21. package/abap/zcl_abgagt_viewer_factory.clas.abap +41 -0
  22. package/abap/zcl_abgagt_viewer_factory.clas.xml +15 -0
  23. package/abap/zcl_abgagt_viewer_intf.clas.abap +58 -0
  24. package/abap/zcl_abgagt_viewer_intf.clas.xml +15 -0
  25. package/abap/zcl_abgagt_viewer_stru.clas.abap +59 -0
  26. package/abap/zcl_abgagt_viewer_stru.clas.xml +15 -0
  27. package/abap/zcl_abgagt_viewer_tabl.clas.abap +59 -0
  28. package/abap/zcl_abgagt_viewer_tabl.clas.xml +15 -0
  29. package/abap/zif_abgagt_command.intf.abap +3 -1
  30. package/abap/zif_abgagt_viewer.intf.abap +11 -0
  31. package/abap/zif_abgagt_viewer.intf.xml +15 -0
  32. package/bin/abapgit-agent +397 -0
  33. package/docs/commands.md +27 -8
  34. package/docs/tree-command.md +303 -0
  35. package/docs/view-command.md +409 -0
  36. package/package.json +1 -1
  37. package/src/abap-client.js +22 -0
  38. package/src/agent.js +27 -0
package/bin/abapgit-agent CHANGED
@@ -495,6 +495,136 @@ async function runUnitTestForFile(sourceFile, csrfToken, config) {
495
495
  }
496
496
  }
497
497
 
498
+ /**
499
+ * Run tree command and return raw result
500
+ */
501
+ async function runTreeCommand(packageName, depth, includeObjects, csrfToken, config) {
502
+ const data = {
503
+ package: packageName,
504
+ depth: depth,
505
+ include_objects: includeObjects
506
+ };
507
+
508
+ return await request('POST', '/sap/bc/z_abapgit_agent/tree', data, { csrfToken });
509
+ }
510
+
511
+ /**
512
+ * Display tree output in human-readable format
513
+ */
514
+ async function displayTreeOutput(packageName, depth, includeObjects) {
515
+ const config = loadConfig();
516
+ const csrfToken = await fetchCsrfToken(config);
517
+
518
+ console.log(`\n Getting package tree for: ${packageName}`);
519
+
520
+ const result = await runTreeCommand(packageName, depth, includeObjects, csrfToken, config);
521
+
522
+ // Handle uppercase keys from ABAP
523
+ const success = result.SUCCESS || result.success;
524
+ const error = result.ERROR || result.error;
525
+
526
+ if (!success || error) {
527
+ console.error(`\n ❌ Error: ${error || 'Failed to get tree'}`);
528
+ return;
529
+ }
530
+
531
+ // Parse hierarchy structure (ABAP returns flat nodes with parent refs)
532
+ const nodes = result.NODES || result.nodes || [];
533
+ const rootPackage = result.PACKAGE || result.package || packageName;
534
+ const parentPackage = result.PARENT_PACKAGE || result.parent_package;
535
+ const totalPackages = result.TOTAL_PACKAGES || result.total_packages || 0;
536
+ const totalObjects = result.TOTAL_OBJECTS || result.total_objects || 0;
537
+ const objectTypes = result.OBJECTS || result.objects || [];
538
+
539
+ console.log(`\n Package Tree: ${rootPackage}`);
540
+
541
+ // Display parent info if available
542
+ if (parentPackage && parentPackage !== rootPackage) {
543
+ console.log(` ⬆️ Parent: ${parentPackage}`);
544
+ }
545
+
546
+ console.log('');
547
+
548
+ // Build and display tree from flat nodes list
549
+ const lines = buildTreeLinesFromNodes(nodes, '', true);
550
+ for (const line of lines) {
551
+ console.log(` ${line}`);
552
+ }
553
+
554
+ console.log('');
555
+ console.log(' Summary');
556
+ console.log(` PACKAGES: ${totalPackages}`);
557
+ console.log(` OBJECTS: ${totalObjects}`);
558
+
559
+ // Display object types if available
560
+ if (includeObjects && objectTypes.length > 0) {
561
+ const typeStr = objectTypes.map(t => `${t.OBJECT || t.object}=${t.COUNT || t.count}`).join(' ');
562
+ console.log(` TYPES: ${typeStr}`);
563
+ }
564
+ }
565
+
566
+ /**
567
+ * Build tree display lines from flat nodes list
568
+ */
569
+ function buildTreeLinesFromNodes(nodes, prefix, isLast) {
570
+ const lines = [];
571
+
572
+ if (nodes.length === 0) {
573
+ return lines;
574
+ }
575
+
576
+ // First node is the root
577
+ const root = nodes[0];
578
+ const icon = '📦';
579
+ lines.push(`${prefix}${isLast ? '└─ ' : '├─ '} ${icon} ${root.PACKAGE || root.package}`);
580
+
581
+ // Get children (nodes with depth > 0, grouped by depth)
582
+ const children = nodes.filter(n => (n.DEPTH || n.depth) > 0);
583
+
584
+ // Group children by depth
585
+ const byDepth = {};
586
+ children.forEach(n => {
587
+ const d = n.DEPTH || n.depth;
588
+ if (!byDepth[d]) byDepth[d] = [];
589
+ byDepth[d].push(n);
590
+ });
591
+
592
+ // Process depth 1 children
593
+ const depth1 = byDepth[1] || [];
594
+ const newPrefix = prefix + (isLast ? ' ' : '│ ');
595
+
596
+ for (let i = 0; i < depth1.length; i++) {
597
+ const child = depth1[i];
598
+ const isSubLast = i === depth1.length - 1;
599
+ const childLines = buildChildLines(child, newPrefix, isSubLast, byDepth);
600
+ lines.push(...childLines);
601
+ }
602
+
603
+ return lines;
604
+ }
605
+
606
+ function buildChildLines(node, prefix, isLast, byDepth) {
607
+ const lines = [];
608
+ const icon = '📦';
609
+ lines.push(`${prefix}${isLast ? '└─ ' : '├─ '} ${icon} ${node.PACKAGE || node.package}`);
610
+
611
+ const newPrefix = prefix + (isLast ? ' ' : '│ ');
612
+ const nodeDepth = node.DEPTH || node.depth;
613
+ const children = byDepth[nodeDepth + 1] || [];
614
+
615
+ // Find children of this node
616
+ const myChildren = children.filter(n => (n.PARENT || n.parent) === (node.PACKAGE || node.package));
617
+
618
+ for (let i = 0; i < myChildren.length; i++) {
619
+ const child = myChildren[i];
620
+ const isSubLast = i === myChildren.length - 1;
621
+ const childLines = buildChildLines(child, newPrefix, isSubLast, byDepth);
622
+ lines.push(...childLines);
623
+ }
624
+
625
+ return lines;
626
+ }
627
+
498
628
  /**
499
629
  * Pull and activate repository
500
630
  */
@@ -818,6 +948,25 @@ async function runInit(args) {
818
948
  console.error(`Error copying CLAUDE.md: ${error.message}`);
819
949
  }
820
950
 
951
+ // Copy copilot-instructions.md for GitHub Copilot
952
+ const copilotMdPath = pathModule.join(__dirname, '..', 'abap', 'copilot-instructions.md');
953
+ const githubDir = pathModule.join(process.cwd(), '.github');
954
+ const localCopilotMdPath = pathModule.join(githubDir, 'copilot-instructions.md');
955
+ try {
956
+ if (fs.existsSync(copilotMdPath)) {
957
+ // Ensure .github directory exists
958
+ if (!fs.existsSync(githubDir)) {
959
+ fs.mkdirSync(githubDir, { recursive: true });
960
+ }
961
+ fs.copyFileSync(copilotMdPath, localCopilotMdPath);
962
+ console.log(`✅ Created .github/copilot-instructions.md`);
963
+ } else {
964
+ console.log(`⚠️ copilot-instructions.md not found in abap/ directory`);
965
+ }
966
+ } catch (error) {
967
+ console.error(`Error copying copilot-instructions.md: ${error.message}`);
968
+ }
969
+
821
970
  // Create folder
822
971
  const folderPath = pathModule.join(process.cwd(), folder);
823
972
  try {
@@ -1173,6 +1322,240 @@ Examples:
1173
1322
  break;
1174
1323
  }
1175
1324
 
1325
+ case 'tree': {
1326
+ const packageArgIndex = args.indexOf('--package');
1327
+ if (packageArgIndex === -1 || packageArgIndex + 1 >= args.length) {
1328
+ console.error('Error: --package parameter required');
1329
+ console.error('Usage: abapgit-agent tree --package <package> [--depth <n>] [--include-objects] [--json]');
1330
+ console.error('Example: abapgit-agent tree --package $ZMY_PACKAGE');
1331
+ process.exit(1);
1332
+ }
1333
+
1334
+ const packageName = args[packageArgIndex + 1];
1335
+
1336
+ // Optional depth parameter
1337
+ const depthArgIndex = args.indexOf('--depth');
1338
+ let depth = 3;
1339
+ if (depthArgIndex !== -1 && depthArgIndex + 1 < args.length) {
1340
+ depth = parseInt(args[depthArgIndex + 1], 10);
1341
+ if (isNaN(depth) || depth < 1) {
1342
+ console.error('Error: --depth must be a positive number');
1343
+ process.exit(1);
1344
+ }
1345
+ }
1346
+
1347
+ // Optional include-objects parameter
1348
+ const includeObjects = args.includes('--include-objects');
1349
+
1350
+ // Optional json parameter
1351
+ const jsonOutput = args.includes('--json');
1352
+
1353
+ if (jsonOutput) {
1354
+ const config = loadConfig();
1355
+ const csrfToken = await fetchCsrfToken(config);
1356
+ const result = await runTreeCommand(packageName, depth, includeObjects, csrfToken, config);
1357
+ console.log(JSON.stringify(result, null, 2));
1358
+ } else {
1359
+ await displayTreeOutput(packageName, depth, includeObjects);
1360
+ }
1361
+ break;
1362
+ }
1363
+
1364
+ case 'view': {
1365
+ const objectsArgIndex = args.indexOf('--objects');
1366
+ if (objectsArgIndex === -1 || objectsArgIndex + 1 >= args.length) {
1367
+ console.error('Error: --objects parameter required');
1368
+ console.error('Usage: abapgit-agent view --objects <obj1>,<obj2>,... [--type <type>] [--json]');
1369
+ console.error('Example: abapgit-agent view --objects ZCL_MY_CLASS');
1370
+ console.error('Example: abapgit-agent view --objects ZCL_CLASS1,ZCL_CLASS2 --type CLAS');
1371
+ process.exit(1);
1372
+ }
1373
+
1374
+ const objects = args[objectsArgIndex + 1].split(',').map(o => o.trim().toUpperCase());
1375
+ const typeArg = args.indexOf('--type');
1376
+ const type = typeArg !== -1 ? args[typeArg + 1].toUpperCase() : null;
1377
+ const jsonOutput = args.includes('--json');
1378
+
1379
+ console.log(`\n Viewing ${objects.length} object(s)`);
1380
+
1381
+ const config = loadConfig();
1382
+ const csrfToken = await fetchCsrfToken(config);
1383
+
1384
+ const data = {
1385
+ objects: objects
1386
+ };
1387
+
1388
+ if (type) {
1389
+ data.type = type;
1390
+ }
1391
+
1392
+ const result = await request('POST', '/sap/bc/z_abapgit_agent/view', data, { csrfToken });
1393
+
1394
+ // Handle uppercase keys from ABAP
1395
+ const success = result.SUCCESS || result.success;
1396
+ const viewObjects = result.OBJECTS || result.objects || [];
1397
+ const message = result.MESSAGE || result.message || '';
1398
+ const error = result.ERROR || result.error;
1399
+
1400
+ if (!success || error) {
1401
+ console.error(`\n Error: ${error || 'Failed to view objects'}`);
1402
+ break;
1403
+ }
1404
+
1405
+ if (jsonOutput) {
1406
+ console.log(JSON.stringify(result, null, 2));
1407
+ } else {
1408
+ console.log(`\n ${message}`);
1409
+ console.log('');
1410
+
1411
+ for (let i = 0; i < viewObjects.length; i++) {
1412
+ const obj = viewObjects[i];
1413
+ const objName = obj.NAME || obj.name || `Object ${i + 1}`;
1414
+ const objType = obj.TYPE || obj.type || '';
1415
+ const objTypeText = obj.TYPE_TEXT || obj.type_text || '';
1416
+ const description = obj.DESCRIPTION || obj.description || '';
1417
+ const methods = obj.METHODS || obj.methods || [];
1418
+ const components = obj.COMPONENTS || obj.components || [];
1419
+ const notFound = obj.NOT_FOUND || obj.not_found || false;
1420
+
1421
+ // Check if object was not found
1422
+ if (notFound) {
1423
+ console.log(` ❌ ${objName} (${objTypeText})`);
1424
+ console.log(` Object not found: ${objName}`);
1425
+ continue;
1426
+ }
1427
+
1428
+ console.log(` 📖 ${objName} (${objTypeText})`);
1429
+ if (description) {
1430
+ console.log(` ${description}`);
1431
+ }
1432
+
1433
+ // Display source code for classes and interfaces
1434
+ const source = obj.SOURCE || obj.source || '';
1435
+ if (source && (objType === 'INTF' || objType === 'Interface' || objType === 'CLAS' || objType === 'Class')) {
1436
+ console.log('');
1437
+ // Replace escaped newlines with actual newlines and display
1438
+ const displaySource = source.replace(/\\n/g, '\n');
1439
+ const lines = displaySource.split('\n');
1440
+ for (const line of lines) {
1441
+ console.log(` ${line}`);
1442
+ }
1443
+ }
1444
+
1445
+ if (methods.length > 0) {
1446
+ console.log(` Methods: ${methods.length}`);
1447
+ for (const method of methods.slice(0, 5)) {
1448
+ const name = method.NAME || method.name || '';
1449
+ const visibility = method.VISIBILITY || method.visibility || '';
1450
+ console.log(` - ${visibility} ${name}`);
1451
+ }
1452
+ if (methods.length > 5) {
1453
+ console.log(` ... and ${methods.length - 5} more`);
1454
+ }
1455
+ }
1456
+
1457
+ if (components.length > 0) {
1458
+ // Check if this is a data element (DTEL) - show domain info in property format
1459
+ if (objType === 'DTEL' || objType === 'Data Element') {
1460
+ const propWidth = 18;
1461
+ const valueWidth = 40;
1462
+
1463
+ // Build separator with corners
1464
+ const sep = '┌' + '─'.repeat(propWidth + 2) + '┬' + '─'.repeat(valueWidth + 2) + '┐';
1465
+ const mid = '├' + '─'.repeat(propWidth + 2) + '┼' + '─'.repeat(valueWidth + 2) + '┤';
1466
+ const end = '└' + '─'.repeat(propWidth + 2) + '┴' + '─'.repeat(valueWidth + 2) + '┘';
1467
+
1468
+ // Helper to build row
1469
+ const buildPropRow = (property, value) => {
1470
+ return '│ ' + String(property || '').padEnd(propWidth) + ' │ ' +
1471
+ String(value || '').substring(0, valueWidth).padEnd(valueWidth) + ' │';
1472
+ };
1473
+
1474
+ console.log(` DATA ELEMENT ${objName}:`);
1475
+ console.log(sep);
1476
+ console.log(buildPropRow('Property', 'Value'));
1477
+ console.log(mid);
1478
+
1479
+ // Collect properties from top-level fields and components
1480
+ const domain = obj.DOMAIN || obj.domain || '';
1481
+ const domainType = obj.DOMAIN_TYPE || obj.domain_type || '';
1482
+ const domainLength = obj.DOMAIN_LENGTH || obj.domain_length || 0;
1483
+ const domainDecimals = obj.DOMAIN_DECIMALS || obj.domain_decimals || 0;
1484
+ const description = obj.DESCRIPTION || obj.description || '';
1485
+
1486
+ if (domainType) {
1487
+ console.log(buildPropRow('Data Type', domainType));
1488
+ }
1489
+ if (domainLength) {
1490
+ console.log(buildPropRow('Length', String(domainLength)));
1491
+ }
1492
+ if (domainDecimals) {
1493
+ console.log(buildPropRow('Decimals', String(domainDecimals)));
1494
+ }
1495
+ if (description) {
1496
+ console.log(buildPropRow('Description', description));
1497
+ }
1498
+ if (domain) {
1499
+ console.log(buildPropRow('Domain', domain));
1500
+ }
1501
+
1502
+ console.log(end);
1503
+ } else {
1504
+ // Build table display for TABL/STRU with Data Element and Description
1505
+ const colWidths = {
1506
+ field: 16, // Max field name length
1507
+ key: 3,
1508
+ type: 8,
1509
+ length: 8,
1510
+ dataelement: 30, // Max data element name length
1511
+ description: 60, // Max field description length
1512
+ };
1513
+
1514
+ // Helper to truncate with ellipsis if needed
1515
+ const truncate = (str, maxLen) => {
1516
+ const s = String(str || '');
1517
+ if (s.length <= maxLen) return s;
1518
+ return s.substring(0, maxLen - 1) + '…';
1519
+ };
1520
+
1521
+ // Helper to build row
1522
+ const buildRow = (field, key, type, length, dataelement, description) => {
1523
+ return ' | ' + truncate(field, colWidths.field).padEnd(colWidths.field) + ' | ' + String(key || '').padEnd(colWidths.key) + ' | ' + truncate(type, colWidths.type).padEnd(colWidths.type) + ' | ' + String(length || '').padStart(colWidths.length) + ' | ' + truncate(dataelement, colWidths.dataelement).padEnd(colWidths.dataelement) + ' | ' + truncate(description, colWidths.description).padEnd(colWidths.description) + ' |';
1524
+ };
1525
+
1526
+ // Build separator line (matches row structure with | at ends and + between columns)
1527
+ const sep = ' |' + '-'.repeat(colWidths.field + 2) + '+' +
1528
+ '-'.repeat(colWidths.key + 2) + '+' +
1529
+ '-'.repeat(colWidths.type + 2) + '+' +
1530
+ '-'.repeat(colWidths.length + 2) + '+' +
1531
+ '-'.repeat(colWidths.dataelement + 2) + '+' +
1532
+ '-'.repeat(colWidths.description + 2) + '|';
1533
+
1534
+ // Header
1535
+ console.log(` TABLE ${objName}:`);
1536
+ console.log(sep);
1537
+ console.log(buildRow('Field', 'Key', 'Type', 'Length', 'Data Elem', 'Description'));
1538
+ console.log(sep);
1539
+
1540
+ // Rows
1541
+ for (const comp of components) {
1542
+ const key = comp.KEY || comp.key || false ? 'X' : '';
1543
+ const dataelement = comp.DATAELEMENT || comp.dataelement || '';
1544
+ const description = comp.DESCRIPTION || comp.description || '';
1545
+ console.log(buildRow(comp.FIELD || comp.field, key, comp.TYPE || comp.type, comp.LENGTH || comp.length, dataelement, description));
1546
+ }
1547
+
1548
+ console.log(sep);
1549
+ }
1550
+ }
1551
+
1552
+ console.log('');
1553
+ }
1554
+
1555
+ }
1556
+ break;
1557
+ }
1558
+
1176
1559
  case 'help':
1177
1560
  case '--help':
1178
1561
  case '-h':
@@ -1206,6 +1589,12 @@ Commands:
1206
1589
  unit --files <file1>,<file2>,...
1207
1590
  Run AUnit tests for ABAP test class files (.testclasses.abap)
1208
1591
 
1592
+ tree --package <package> [--depth <n>] [--include-objects] [--json]
1593
+ Display package hierarchy tree from ABAP system
1594
+
1595
+ view --objects <obj1>,<obj2>,... [--type <type>] [--json]
1596
+ View ABAP object definitions from the ABAP system
1597
+
1209
1598
  health
1210
1599
  Check if ABAP REST API is healthy
1211
1600
 
@@ -1223,6 +1612,14 @@ Examples:
1223
1612
  abapgit-agent pull --transport DEVK900001 # With transport
1224
1613
  abapgit-agent inspect --files zcl_my_class.clas.abap # Syntax check
1225
1614
  abapgit-agent unit --files zcl_my_test.clas.testclasses.abap # Run tests
1615
+ abapgit-agent tree --package $ZMY_PACKAGE # Show package tree
1616
+ abapgit-agent tree --package $ZMY_PACKAGE --depth 2 # Shallow tree
1617
+ abapgit-agent tree --package $ZMY_PACKAGE --include-objects # With object counts
1618
+ abapgit-agent tree --package $ZMY_PACKAGE --json # JSON output
1619
+ abapgit-agent view --objects ZCL_MY_CLASS # View class definition
1620
+ abapgit-agent view --objects ZIF_MY_INTERFACE --type INTF # View interface
1621
+ abapgit-agent view --objects ZMY_TABLE --type TABL # View table structure
1622
+ abapgit-agent view --objects ZCL_CLASS1,ZCL_CLASS2 --json # Multiple objects
1226
1623
  abapgit-agent health
1227
1624
  abapgit-agent status
1228
1625
  `);
package/docs/commands.md CHANGED
@@ -11,7 +11,9 @@ All available CLI commands for abapGit Agent.
11
11
  | [import](import-command.md) | ✅ | Import objects from ABAP package to git |
12
12
  | [pull](pull-command.md) | ✅ | Pull and activate objects in ABAP |
13
13
  | [inspect](inspect-command.md) | ✅ | Syntax check ABAP source files |
14
+ | [tree](tree-command.md) | ✅ | Display package hierarchy tree |
14
15
  | [unit](unit-command.md) | ✅ | Run AUnit tests |
16
+ | [view](view-command.md) | ✅ | View ABAP object source code from system |
15
17
  | [health](health-command.md) | ✅ | Health check |
16
18
  | [status](status-command.md) | ✅ | Status check |
17
19
 
@@ -23,21 +25,24 @@ All available CLI commands for abapGit Agent.
23
25
 
24
26
  ```bash
25
27
  # 1. Initialize local configuration
26
- abapgit-agent init --folder /src --package ZMY_PACKAGE
28
+ abapgit-agent init --folder /src/ --package ZMY_PACKAGE
27
29
 
28
30
  # 2. Edit .abapGitAgent with credentials
29
31
  vim .abapGitAgent
30
32
 
31
- # 3. Create online repository in ABAP
33
+ # 3. Commit and push new files to git
34
+ git add . && git commit -m "Initial commit" && git push origin main
35
+
36
+ # 4. Create online repository in ABAP
32
37
  abapgit-agent create
33
38
 
34
- # 4. Import objects from ABAP package to git
39
+ # 5. Import objects from ABAP package to git
35
40
  abapgit-agent import
36
41
 
37
- # 5. Push to git
38
- git push origin main
42
+ # 6. Pull new objects imported from ABAP package
43
+ git pull origin main
39
44
 
40
- # 6. Activate in ABAP
45
+ # 7. Activate in ABAP
41
46
  abapgit-agent pull
42
47
  ```
43
48
 
@@ -58,6 +63,13 @@ abapgit-agent inspect --files abap/zcl_my_class.clas.abap
58
63
  # Run unit tests
59
64
  abapgit-agent unit --files abap/zcl_my_test.clas.testclasses.abap
60
65
 
66
+ # Display package hierarchy
67
+ abapgit-agent tree --package $MY_PACKAGE
68
+
69
+ # View object definitions (classes, interfaces, tables, data elements)
70
+ abapgit-agent view --objects ZCL_MY_CLASS
71
+ abapgit-agent view --objects SFLIGHT --type TABL
72
+
61
73
  # Check configuration
62
74
  abapgit-agent status
63
75
 
@@ -77,6 +89,12 @@ abapgit-agent health
77
89
 
78
90
 
79
91
  ┌─────────────────────────────────────────────────┐
92
+ │ git add && git commit && git push │
93
+ │ └── Push initial files to git │
94
+ └─────────────────────────────────────────────────┘
95
+
96
+
97
+ ┌─────────────────────────────────────────────────┐
80
98
  │ create │
81
99
  │ └── Creates online repo in ABAP │
82
100
  └─────────────────────────────────────────────────┘
@@ -84,12 +102,13 @@ abapgit-agent health
84
102
 
85
103
  ┌─────────────────────────────────────────────────┐
86
104
  │ import │
87
- │ └── Stages, commits, pushes objects to git
105
+ │ └── Stages, commits, pushes objects to git
88
106
  └─────────────────────────────────────────────────┘
89
107
 
90
108
 
91
109
  ┌─────────────────────────────────────────────────┐
92
- │ git push
110
+ │ git pull
111
+ │ └── Pull imported objects from ABAP package │
93
112
  └─────────────────────────────────────────────────┘
94
113
 
95
114