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,111 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Help command - Display usage information
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
module.exports = {
|
|
6
|
+
name: 'help',
|
|
7
|
+
description: 'Display usage information and available commands',
|
|
8
|
+
requiresAbapConfig: false,
|
|
9
|
+
requiresVersionCheck: false,
|
|
10
|
+
|
|
11
|
+
async execute(args, context) {
|
|
12
|
+
console.log(`
|
|
13
|
+
ABAP Git Agent
|
|
14
|
+
|
|
15
|
+
Usage:
|
|
16
|
+
abapgit-agent <command> [options]
|
|
17
|
+
|
|
18
|
+
Commands:
|
|
19
|
+
init --folder <folder> --package <package>
|
|
20
|
+
Initialize local configuration for an existing git repository.
|
|
21
|
+
init --update
|
|
22
|
+
Update existing files (CLAUDE.md, copilot-instructions.md, guidelines) to latest version.
|
|
23
|
+
|
|
24
|
+
create
|
|
25
|
+
Create abapGit online repository in ABAP system.
|
|
26
|
+
Auto-detects URL from git remote and package from .abapGitAgent.
|
|
27
|
+
|
|
28
|
+
import [--message <message>]
|
|
29
|
+
Import existing objects from package to git repository.
|
|
30
|
+
Uses the git remote URL to find the abapGit online repository.
|
|
31
|
+
|
|
32
|
+
pull [--url <git-url>] [--branch <branch>] [--files <file1,file2,...>] [--transport <request>]
|
|
33
|
+
Pull and activate repository in ABAP system.
|
|
34
|
+
Auto-detects git remote and branch from current directory.
|
|
35
|
+
Use --files to pull only specific files.
|
|
36
|
+
Use --transport to specify a transport request.
|
|
37
|
+
|
|
38
|
+
inspect --files <file1>,<file2>,...
|
|
39
|
+
Inspect ABAP source file(s) for issues. Currently runs syntax check.
|
|
40
|
+
|
|
41
|
+
syntax --files <file1>,<file2>,... [--cloud] [--json]
|
|
42
|
+
Check syntax of ABAP source files WITHOUT pull/activation.
|
|
43
|
+
Reads source from local files and checks directly in ABAP system.
|
|
44
|
+
Use --cloud for ABAP Cloud (BTP) stricter syntax checking.
|
|
45
|
+
|
|
46
|
+
unit --files <file1>,<file2>,...
|
|
47
|
+
Run AUnit tests for ABAP test class files (.testclasses.abap)
|
|
48
|
+
|
|
49
|
+
tree --package <package> [--depth <n>] [--include-types] [--json]
|
|
50
|
+
Display package hierarchy tree from ABAP system
|
|
51
|
+
|
|
52
|
+
list --package <package> [--type <types>] [--name <pattern>] [--limit <n>] [--offset <n>] [--json]
|
|
53
|
+
List ABAP objects in a package with filtering and pagination
|
|
54
|
+
|
|
55
|
+
view --objects <obj1>,<obj2>,... [--type <type>] [--json]
|
|
56
|
+
View ABAP object definitions from the ABAP system
|
|
57
|
+
|
|
58
|
+
where --objects <obj1>,<obj2>,... [--type <type>] [--limit <n>] [--json]
|
|
59
|
+
Find where-used list for ABAP objects (classes, interfaces, programs)
|
|
60
|
+
|
|
61
|
+
ref <pattern> [--json]
|
|
62
|
+
Search ABAP reference repositories for patterns. Requires referenceFolder in .abapGitAgent.
|
|
63
|
+
|
|
64
|
+
ref --topic <topic> [--json]
|
|
65
|
+
View specific topic from cheat sheets (exceptions, sql, unit-tests, etc.)
|
|
66
|
+
|
|
67
|
+
ref --list-topics
|
|
68
|
+
List available topics for reference search
|
|
69
|
+
|
|
70
|
+
ref --list-repos
|
|
71
|
+
List all reference repositories in the reference folder
|
|
72
|
+
|
|
73
|
+
ref --clone <repo> [--name <folder>]
|
|
74
|
+
Clone a GitHub repository to the reference folder
|
|
75
|
+
- Use full URL: https://github.com/user/repo.git
|
|
76
|
+
- Or short name: user/repo or user/repo (assumes github.com)
|
|
77
|
+
|
|
78
|
+
health
|
|
79
|
+
Check if ABAP REST API is healthy
|
|
80
|
+
|
|
81
|
+
status
|
|
82
|
+
Check if ABAP integration is configured for this repo
|
|
83
|
+
|
|
84
|
+
Examples:
|
|
85
|
+
abapgit-agent init --folder /src --package ZMY_PACKAGE # Initialize
|
|
86
|
+
abapgit-agent init --update # Update files to latest
|
|
87
|
+
abapgit-agent create # Create repo
|
|
88
|
+
abapgit-agent delete # Delete repo
|
|
89
|
+
abapgit-agent import # Import objects to git
|
|
90
|
+
abapgit-agent import --message "Initial import" # Import with message
|
|
91
|
+
abapgit-agent pull # Auto-detect from git
|
|
92
|
+
abapgit-agent pull --branch develop # Specific branch
|
|
93
|
+
abapgit-agent pull --files src/zcl_my_class.clas.abap # Specific file
|
|
94
|
+
abapgit-agent pull --transport DEVK900001 # With transport
|
|
95
|
+
abapgit-agent inspect --files src/zcl_my_class.clas.abap # Syntax check
|
|
96
|
+
abapgit-agent syntax --files src/zcl_my_class.clas.abap # Check without pull
|
|
97
|
+
abapgit-agent syntax --files src/zmy_prog.prog.abap --cloud # ABAP Cloud check
|
|
98
|
+
abapgit-agent unit --files src/zcl_my_test.clas.testclasses.abap # Run unit tests
|
|
99
|
+
abapgit-agent tree --package $MY_PACKAGE # Display package tree
|
|
100
|
+
abapgit-agent list --package $MY_PACKAGE --type CLAS,INTF # List classes & interfaces
|
|
101
|
+
abapgit-agent view --objects ZCL_MY_CLASS # View class definition
|
|
102
|
+
abapgit-agent where --objects ZCL_MY_CLASS # Find where class is used
|
|
103
|
+
abapgit-agent ref "CORRESPONDING" # Search for pattern
|
|
104
|
+
abapgit-agent ref --topic exceptions # View exceptions topic
|
|
105
|
+
abapgit-agent health # Health check
|
|
106
|
+
abapgit-agent status # Configuration status
|
|
107
|
+
|
|
108
|
+
For more info: https://github.tools.sap/I045696/abapgit-agent
|
|
109
|
+
`);
|
|
110
|
+
}
|
|
111
|
+
};
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Import command - Import existing objects from package to git repository
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
module.exports = {
|
|
6
|
+
name: 'import',
|
|
7
|
+
description: 'Import existing objects from package to git repository',
|
|
8
|
+
requiresAbapConfig: true,
|
|
9
|
+
requiresVersionCheck: true,
|
|
10
|
+
|
|
11
|
+
async execute(args, context) {
|
|
12
|
+
const { loadConfig, gitUtils, AbapHttp } = context;
|
|
13
|
+
|
|
14
|
+
// Show help if requested
|
|
15
|
+
const helpIndex = args.findIndex(a => a === '--help' || a === '-h');
|
|
16
|
+
if (helpIndex !== -1) {
|
|
17
|
+
console.log(`
|
|
18
|
+
Usage:
|
|
19
|
+
abapgit-agent import [--message <message>]
|
|
20
|
+
|
|
21
|
+
Description:
|
|
22
|
+
Import existing objects from package to git repository.
|
|
23
|
+
Uses the git remote URL to find the abapGit online repository.
|
|
24
|
+
|
|
25
|
+
Prerequisites:
|
|
26
|
+
- Run "abapgit-agent create" first or create repository in abapGit UI
|
|
27
|
+
- Package must have objects to import
|
|
28
|
+
|
|
29
|
+
Options:
|
|
30
|
+
--message Commit message (default: "feat: initial import from ABAP package <package>")
|
|
31
|
+
|
|
32
|
+
Examples:
|
|
33
|
+
abapgit-agent import
|
|
34
|
+
abapgit-agent import --message "Initial import from SAP"
|
|
35
|
+
`);
|
|
36
|
+
return;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
// Get parameters from config
|
|
40
|
+
const config = loadConfig();
|
|
41
|
+
const repoUrl = gitUtils.getRemoteUrl();
|
|
42
|
+
|
|
43
|
+
if (!repoUrl) {
|
|
44
|
+
console.error('Error: No git remote configured. Please configure a remote origin.');
|
|
45
|
+
process.exit(1);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
const messageArgIndex = args.indexOf('--message');
|
|
49
|
+
let commitMessage = null;
|
|
50
|
+
if (messageArgIndex !== -1 && messageArgIndex + 1 < args.length) {
|
|
51
|
+
commitMessage = args[messageArgIndex + 1];
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
console.log(`\n📦 Importing objects to git repository`);
|
|
55
|
+
console.log(` URL: ${repoUrl}`);
|
|
56
|
+
if (commitMessage) {
|
|
57
|
+
console.log(` Message: ${commitMessage}`);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
const http = new AbapHttp(config);
|
|
61
|
+
const csrfToken = await http.fetchCsrfToken();
|
|
62
|
+
|
|
63
|
+
const data = {
|
|
64
|
+
url: repoUrl
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
if (commitMessage) {
|
|
68
|
+
data.message = commitMessage;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
if (config.gitUsername) {
|
|
72
|
+
data.username = config.gitUsername;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
if (config.gitPassword) {
|
|
76
|
+
data.password = config.gitPassword;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
const result = await http.post('/sap/bc/z_abapgit_agent/import', data, { csrfToken });
|
|
80
|
+
|
|
81
|
+
console.log('\n');
|
|
82
|
+
|
|
83
|
+
// Handle uppercase keys from ABAP
|
|
84
|
+
const success = result.SUCCESS || result.success;
|
|
85
|
+
const filesStaged = result.FILES_STAGED || result.files_staged;
|
|
86
|
+
const abapCommitMessage = result.COMMIT_MESSAGE || result.commit_message;
|
|
87
|
+
const error = result.ERROR || result.error;
|
|
88
|
+
|
|
89
|
+
if (success === 'X' || success === true) {
|
|
90
|
+
console.log(`✅ Objects imported successfully!`);
|
|
91
|
+
console.log(` Files staged: ${filesStaged}`);
|
|
92
|
+
console.log(` Commit: ${commitMessage || abapCommitMessage}`);
|
|
93
|
+
} else {
|
|
94
|
+
console.log(`❌ Import failed`);
|
|
95
|
+
console.log(` Error: ${error || 'Unknown error'}`);
|
|
96
|
+
process.exit(1);
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
};
|
|
@@ -0,0 +1,321 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Init command - Initialize local repository configuration
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
const pathModule = require('path');
|
|
6
|
+
const fs = require('fs');
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Copy a file if source exists (helper for init --update)
|
|
10
|
+
*/
|
|
11
|
+
async function copyFileIfExists(srcPath, destPath, label, createParentDir = false) {
|
|
12
|
+
try {
|
|
13
|
+
if (fs.existsSync(srcPath)) {
|
|
14
|
+
if (createParentDir) {
|
|
15
|
+
const parentDir = pathModule.dirname(destPath);
|
|
16
|
+
if (!fs.existsSync(parentDir)) {
|
|
17
|
+
fs.mkdirSync(parentDir, { recursive: true });
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
fs.copyFileSync(srcPath, destPath);
|
|
21
|
+
console.log(`✅ Updated ${label}`);
|
|
22
|
+
} else {
|
|
23
|
+
console.log(`⚠️ ${label} not found in abapgit-agent`);
|
|
24
|
+
}
|
|
25
|
+
} catch (error) {
|
|
26
|
+
console.error(`Error copying ${label}: ${error.message}`);
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Copy guidelines folder (helper for init --update)
|
|
32
|
+
*/
|
|
33
|
+
async function copyGuidelinesFolder(srcPath, destPath, overwrite = false) {
|
|
34
|
+
try {
|
|
35
|
+
if (fs.existsSync(srcPath)) {
|
|
36
|
+
// Create destination directory if needed
|
|
37
|
+
if (!fs.existsSync(destPath)) {
|
|
38
|
+
fs.mkdirSync(destPath, { recursive: true });
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
const files = fs.readdirSync(srcPath);
|
|
42
|
+
let copied = 0;
|
|
43
|
+
|
|
44
|
+
for (const file of files) {
|
|
45
|
+
if (file.endsWith('.md')) {
|
|
46
|
+
const srcFile = pathModule.join(srcPath, file);
|
|
47
|
+
const destFile = pathModule.join(destPath, file);
|
|
48
|
+
|
|
49
|
+
// Skip if file exists and not overwriting
|
|
50
|
+
if (fs.existsSync(destFile) && !overwrite) {
|
|
51
|
+
continue;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
fs.copyFileSync(srcFile, destFile);
|
|
55
|
+
copied++;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
if (copied > 0) {
|
|
60
|
+
console.log(`✅ Updated guidelines/ (${copied} files)`);
|
|
61
|
+
} else {
|
|
62
|
+
console.log(`⚠️ No guideline files found`);
|
|
63
|
+
}
|
|
64
|
+
} else {
|
|
65
|
+
console.log(`⚠️ guidelines folder not found in abapgit-agent`);
|
|
66
|
+
}
|
|
67
|
+
} catch (error) {
|
|
68
|
+
console.error(`Error copying guidelines: ${error.message}`);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
module.exports = {
|
|
73
|
+
name: 'init',
|
|
74
|
+
description: 'Initialize local repository configuration',
|
|
75
|
+
requiresAbapConfig: false,
|
|
76
|
+
requiresVersionCheck: false,
|
|
77
|
+
|
|
78
|
+
async execute(args, context) {
|
|
79
|
+
const { gitUtils } = context;
|
|
80
|
+
|
|
81
|
+
const folderArgIndex = args.indexOf('--folder');
|
|
82
|
+
const packageArgIndex = args.indexOf('--package');
|
|
83
|
+
const updateMode = args.includes('--update');
|
|
84
|
+
|
|
85
|
+
// Get parameters
|
|
86
|
+
let folder = folderArgIndex !== -1 && folderArgIndex + 1 < args.length
|
|
87
|
+
? args[folderArgIndex + 1]
|
|
88
|
+
: '/src/';
|
|
89
|
+
|
|
90
|
+
// Normalize folder path: ensure it starts with / and ends with /
|
|
91
|
+
folder = folder.trim();
|
|
92
|
+
if (!folder.startsWith('/')) {
|
|
93
|
+
folder = '/' + folder;
|
|
94
|
+
}
|
|
95
|
+
if (!folder.endsWith('/')) {
|
|
96
|
+
folder = folder + '/';
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
const packageName = packageArgIndex !== -1 && packageArgIndex + 1 < args.length
|
|
100
|
+
? args[packageArgIndex + 1]
|
|
101
|
+
: null;
|
|
102
|
+
|
|
103
|
+
// Validate package is required for non-update mode
|
|
104
|
+
if (!updateMode && !packageName) {
|
|
105
|
+
console.error('Error: --package is required');
|
|
106
|
+
console.error('Usage: abapgit-agent init --folder /src --package ZMY_PACKAGE');
|
|
107
|
+
console.error(' abapgit-agent init --update # Update files to latest version');
|
|
108
|
+
process.exit(1);
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
// Check if current folder is git repo root
|
|
112
|
+
const gitDir = pathModule.join(process.cwd(), '.git');
|
|
113
|
+
if (!fs.existsSync(gitDir)) {
|
|
114
|
+
console.error('Error: Current folder is not a git repository.');
|
|
115
|
+
console.error('Run this command from the root folder of your git repository.');
|
|
116
|
+
process.exit(1);
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
// In update mode, just copy the files and return
|
|
120
|
+
if (updateMode) {
|
|
121
|
+
console.log(`\n🔄 Updating abapGit Agent files`);
|
|
122
|
+
console.log('');
|
|
123
|
+
|
|
124
|
+
// Copy CLAUDE.md
|
|
125
|
+
await copyFileIfExists(
|
|
126
|
+
pathModule.join(__dirname, '..', '..', 'abap', 'CLAUDE.md'),
|
|
127
|
+
pathModule.join(process.cwd(), 'CLAUDE.md'),
|
|
128
|
+
'CLAUDE.md'
|
|
129
|
+
);
|
|
130
|
+
|
|
131
|
+
// Copy copilot-instructions.md
|
|
132
|
+
await copyFileIfExists(
|
|
133
|
+
pathModule.join(__dirname, '..', '..', 'abap', '.github', 'copilot-instructions.md'),
|
|
134
|
+
pathModule.join(process.cwd(), '.github', 'copilot-instructions.md'),
|
|
135
|
+
'.github/copilot-instructions.md',
|
|
136
|
+
true // create parent dir
|
|
137
|
+
);
|
|
138
|
+
|
|
139
|
+
// Copy guidelines folder to project root
|
|
140
|
+
await copyGuidelinesFolder(
|
|
141
|
+
pathModule.join(__dirname, '..', '..', 'abap', 'guidelines'),
|
|
142
|
+
pathModule.join(process.cwd(), 'guidelines'),
|
|
143
|
+
true // overwrite
|
|
144
|
+
);
|
|
145
|
+
|
|
146
|
+
console.log(`
|
|
147
|
+
📋 Update complete!
|
|
148
|
+
Run 'abapgit-agent ref --list-topics' to see available topics.
|
|
149
|
+
`);
|
|
150
|
+
return;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
// Validate package is required
|
|
154
|
+
if (!packageName) {
|
|
155
|
+
console.error('Error: --package is required');
|
|
156
|
+
console.error('Usage: abapgit-agent init --folder /src --package ZMY_PACKAGE');
|
|
157
|
+
console.error(' abapgit-agent init --update # Update files to latest version');
|
|
158
|
+
process.exit(1);
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
console.log(`\n🚀 Initializing abapGit Agent for local repository`);
|
|
162
|
+
console.log(` Folder: ${folder}`);
|
|
163
|
+
console.log(` Package: ${packageName}`);
|
|
164
|
+
console.log('');
|
|
165
|
+
|
|
166
|
+
// Detect git remote URL
|
|
167
|
+
const gitUrl = gitUtils.getRemoteUrl();
|
|
168
|
+
if (!gitUrl) {
|
|
169
|
+
console.error('Error: No git remote configured.');
|
|
170
|
+
console.error('Configure a remote with: git remote add origin <url>');
|
|
171
|
+
process.exit(1);
|
|
172
|
+
}
|
|
173
|
+
console.log(`📌 Git remote: ${gitUrl}`);
|
|
174
|
+
|
|
175
|
+
// Check if .abapGitAgent already exists
|
|
176
|
+
const configPath = pathModule.join(process.cwd(), '.abapGitAgent');
|
|
177
|
+
if (fs.existsSync(configPath)) {
|
|
178
|
+
console.error('Error: .abapGitAgent already exists.');
|
|
179
|
+
console.error('To reinitialize, delete the existing file first.');
|
|
180
|
+
process.exit(1);
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
// Copy .abapGitAgent.example to .abapGitAgent
|
|
184
|
+
const samplePath = pathModule.join(__dirname, '..', '..', '.abapGitAgent.example');
|
|
185
|
+
if (!fs.existsSync(samplePath)) {
|
|
186
|
+
console.error('Error: .abapGitAgent.example not found.');
|
|
187
|
+
process.exit(1);
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
try {
|
|
191
|
+
// Read sample and update with package/folder
|
|
192
|
+
const sampleContent = fs.readFileSync(samplePath, 'utf8');
|
|
193
|
+
const config = JSON.parse(sampleContent);
|
|
194
|
+
config.package = packageName;
|
|
195
|
+
config.folder = folder;
|
|
196
|
+
|
|
197
|
+
// Write updated config
|
|
198
|
+
fs.writeFileSync(configPath, JSON.stringify(config, null, 2) + '\n');
|
|
199
|
+
console.log(`✅ Created .abapGitAgent`);
|
|
200
|
+
} catch (error) {
|
|
201
|
+
console.error(`Error creating .abapGitAgent: ${error.message}`);
|
|
202
|
+
process.exit(1);
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
// Update .gitignore
|
|
206
|
+
const gitignorePath = pathModule.join(process.cwd(), '.gitignore');
|
|
207
|
+
const ignoreEntries = ['.abapGitAgent', '.abapgit_agent_cookies.txt'];
|
|
208
|
+
let existingIgnore = '';
|
|
209
|
+
|
|
210
|
+
if (fs.existsSync(gitignorePath)) {
|
|
211
|
+
existingIgnore = fs.readFileSync(gitignorePath, 'utf8');
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
let updated = false;
|
|
215
|
+
let newIgnoreContent = existingIgnore;
|
|
216
|
+
|
|
217
|
+
for (const entry of ignoreEntries) {
|
|
218
|
+
if (!newIgnoreContent.includes(entry)) {
|
|
219
|
+
if (newIgnoreContent && !newIgnoreContent.endsWith('\n')) {
|
|
220
|
+
newIgnoreContent += '\n';
|
|
221
|
+
}
|
|
222
|
+
newIgnoreContent += entry + '\n';
|
|
223
|
+
updated = true;
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
if (updated) {
|
|
228
|
+
fs.writeFileSync(gitignorePath, newIgnoreContent);
|
|
229
|
+
console.log(`✅ Updated .gitignore`);
|
|
230
|
+
} else {
|
|
231
|
+
fs.writeFileSync(gitignorePath, newIgnoreContent);
|
|
232
|
+
console.log(`✅ .gitignore already up to date`);
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
// Copy CLAUDE.md
|
|
236
|
+
const claudeMdPath = pathModule.join(__dirname, '..', '..', 'abap', 'CLAUDE.md');
|
|
237
|
+
const localClaudeMdPath = pathModule.join(process.cwd(), 'CLAUDE.md');
|
|
238
|
+
try {
|
|
239
|
+
if (fs.existsSync(claudeMdPath)) {
|
|
240
|
+
fs.copyFileSync(claudeMdPath, localClaudeMdPath);
|
|
241
|
+
console.log(`✅ Created CLAUDE.md`);
|
|
242
|
+
} else {
|
|
243
|
+
console.log(`⚠️ CLAUDE.md not found in abap/ directory`);
|
|
244
|
+
}
|
|
245
|
+
} catch (error) {
|
|
246
|
+
console.error(`Error copying CLAUDE.md: ${error.message}`);
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
// Copy copilot-instructions.md for GitHub Copilot
|
|
250
|
+
const copilotMdPath = pathModule.join(__dirname, '..', '..', 'abap', '.github', 'copilot-instructions.md');
|
|
251
|
+
const githubDir = pathModule.join(process.cwd(), '.github');
|
|
252
|
+
const localCopilotMdPath = pathModule.join(githubDir, 'copilot-instructions.md');
|
|
253
|
+
try {
|
|
254
|
+
if (fs.existsSync(copilotMdPath)) {
|
|
255
|
+
// Ensure .github directory exists
|
|
256
|
+
if (!fs.existsSync(githubDir)) {
|
|
257
|
+
fs.mkdirSync(githubDir, { recursive: true });
|
|
258
|
+
}
|
|
259
|
+
fs.copyFileSync(copilotMdPath, localCopilotMdPath);
|
|
260
|
+
console.log(`✅ Created .github/copilot-instructions.md`);
|
|
261
|
+
} else {
|
|
262
|
+
console.log(`⚠️ copilot-instructions.md not found in abap/ directory`);
|
|
263
|
+
}
|
|
264
|
+
} catch (error) {
|
|
265
|
+
console.error(`Error copying copilot-instructions.md: ${error.message}`);
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
// Copy guidelines folder to project root
|
|
269
|
+
const guidelinesSrcPath = pathModule.join(__dirname, '..', '..', 'abap', 'guidelines');
|
|
270
|
+
const guidelinesDestPath = pathModule.join(process.cwd(), 'guidelines');
|
|
271
|
+
try {
|
|
272
|
+
if (fs.existsSync(guidelinesSrcPath)) {
|
|
273
|
+
if (!fs.existsSync(guidelinesDestPath)) {
|
|
274
|
+
// Create guidelines directory
|
|
275
|
+
fs.mkdirSync(guidelinesDestPath, { recursive: true });
|
|
276
|
+
// Copy all files from guidelines folder
|
|
277
|
+
const files = fs.readdirSync(guidelinesSrcPath);
|
|
278
|
+
for (const file of files) {
|
|
279
|
+
if (file.endsWith('.md')) {
|
|
280
|
+
fs.copyFileSync(
|
|
281
|
+
pathModule.join(guidelinesSrcPath, file),
|
|
282
|
+
pathModule.join(guidelinesDestPath, file)
|
|
283
|
+
);
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
console.log(`✅ Created guidelines/ (${files.filter(f => f.endsWith('.md')).length} files)`);
|
|
287
|
+
} else {
|
|
288
|
+
console.log(`⚠️ guidelines/ already exists, skipped`);
|
|
289
|
+
}
|
|
290
|
+
} else {
|
|
291
|
+
console.log(`⚠️ guidelines folder not found in abap/ directory`);
|
|
292
|
+
}
|
|
293
|
+
} catch (error) {
|
|
294
|
+
console.error(`Error copying guidelines: ${error.message}`);
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
// Create folder
|
|
298
|
+
const folderPath = pathModule.join(process.cwd(), folder);
|
|
299
|
+
try {
|
|
300
|
+
if (!fs.existsSync(folderPath)) {
|
|
301
|
+
fs.mkdirSync(folderPath, { recursive: true });
|
|
302
|
+
console.log(`✅ Created folder: ${folder}`);
|
|
303
|
+
|
|
304
|
+
// Create .gitkeep
|
|
305
|
+
const gitkeepPath = pathModule.join(folderPath, '.gitkeep');
|
|
306
|
+
fs.writeFileSync(gitkeepPath, '');
|
|
307
|
+
} else {
|
|
308
|
+
console.log(`✅ Folder already exists: ${folder}`);
|
|
309
|
+
}
|
|
310
|
+
} catch (error) {
|
|
311
|
+
console.error(`Error creating folder: ${error.message}`);
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
console.log(`
|
|
315
|
+
📋 Next steps:
|
|
316
|
+
1. Edit .abapGitAgent with your ABAP credentials (host, user, password)
|
|
317
|
+
2. Run 'abapgit-agent create --import' to create online repository
|
|
318
|
+
3. Run 'abapgit-agent pull' to activate objects
|
|
319
|
+
`);
|
|
320
|
+
}
|
|
321
|
+
};
|