abapgit-agent 1.15.0 → 1.15.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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "abapgit-agent",
3
- "version": "1.15.0",
3
+ "version": "1.15.1",
4
4
  "description": "ABAP Git Agent - Pull and activate ABAP code via abapGit from any git repository",
5
5
  "files": [
6
6
  "bin/",
@@ -37,6 +37,7 @@
37
37
  "test:cmd:tree": "node tests/run-all.js --cmd --command=tree",
38
38
  "test:cmd:dump": "node tests/run-all.js --cmd --command=dump",
39
39
  "test:cmd:debug": "node tests/run-all.js --cmd --command=debug",
40
+ "test:debug": "node tests/run-all.js --debug",
40
41
  "test:debug:scenarios": "bash tests/integration/debug-scenarios.sh",
41
42
  "test:debug:scenarios:1": "bash tests/integration/debug-scenarios.sh 1",
42
43
  "test:debug:scenarios:2": "bash tests/integration/debug-scenarios.sh 2",
@@ -109,8 +109,23 @@ function objectUri(name, includeType) {
109
109
  }
110
110
  // FUGR source includes: L<group>U<NN>, L<group>TOP, L<group>F<NN>, etc.
111
111
  // All start with 'L'. Customer Z/Y programs never start with 'L'.
112
+ // Correct ADT URI (verified against abap-adt-api):
113
+ // /sap/bc/adt/functions/groups/<group>/includes/<include>/source/main
114
+ // NOT /programs/includes/ — that path is for standalone PROG/I includes only.
115
+ // Group name is derived by stripping leading 'L' and trailing suffix:
116
+ // U<NN> — FM source include (U01, U02, ...)
117
+ // TOP — pool include
118
+ // F<NN> — form include
119
+ // XX — internal include
112
120
  if (/^L/.test(upper)) {
113
- return `/sap/bc/adt/programs/includes/${lower}`;
121
+ const withoutL = upper.slice(1); // e.g. ZCAIS_DEMOU01
122
+ const group = withoutL
123
+ .replace(/U\d+$/, '') // strip Unn suffix
124
+ .replace(/TOP$/, '') // strip TOP suffix
125
+ .replace(/F\d+$/, '') // strip Fnn suffix
126
+ .replace(/XX$/, '') // strip XX suffix
127
+ .toLowerCase();
128
+ return `/sap/bc/adt/functions/groups/${group}/includes/${lower}/source/main`;
114
129
  }
115
130
  return `/sap/bc/adt/programs/programs/${lower}`;
116
131
  }
@@ -236,15 +251,25 @@ async function refreshBreakpoints(config, adt, bps) {
236
251
 
237
252
  const serverResults = parseBreakpointResponse(resp.body || '', bps);
238
253
 
239
- // Match server results back to local bps by uri+line
254
+ // Match server results back to local bps by uri+line.
255
+ // ADT may return a different canonical URI than what was sent (e.g. it rewrites
256
+ // /functions/groups/<g>/includes/<inc>/... to /functions/groups/<g>/fmodules/<fm>/...).
257
+ // Fall back to matching by line alone when URI doesn't match, then adopt the
258
+ // server's canonical URI so future refreshes continue to work.
240
259
  const valid = [];
241
260
  const stale = [];
242
261
  for (const bp of bps) {
243
- const match = serverResults.find(r => r.uri === bp.uri && r.line === bp.line);
262
+ let match = serverResults.find(r => r.uri === bp.uri && r.line === bp.line);
263
+ if (!match) {
264
+ // Fallback: match by line number alone (handles URI canonicalization by ADT)
265
+ match = serverResults.find(r => r.line === bp.line);
266
+ }
244
267
  if (match && match.error) {
245
268
  stale.push({ ...bp, error: match.error });
246
269
  } else if (match && match.id) {
247
- valid.push({ ...bp, id: match.id });
270
+ // Adopt the server's canonical URI so subsequent refreshes match correctly
271
+ const canonicalUri = match.uri || bp.uri;
272
+ valid.push({ ...bp, id: match.id, uri: canonicalUri });
248
273
  } else {
249
274
  // No match in response — server silently dropped it (e.g. expired)
250
275
  stale.push({ ...bp, error: 'Not registered on server' });
@@ -398,9 +423,16 @@ async function cmdSet(args, config, adt) {
398
423
  }
399
424
 
400
425
  // Update local state with server-assigned IDs
426
+ // Use URI+line match first; fall back to line-only for FUGR where ADT rewrites
427
+ // /includes/<inc>/ to /fmodules/<fm>/ in the response.
401
428
  const updatedWithServerIds = updated.map(bp => {
402
- const sr = serverResults.find(r => r.uri === bp.uri && r.line === bp.line);
403
- return sr && sr.id ? { ...bp, id: sr.id } : bp;
429
+ const sr = serverResults.find(r => r.uri === bp.uri && r.line === bp.line)
430
+ || serverResults.find(r => r.line === bp.line);
431
+ if (sr && sr.id) {
432
+ const canonicalUri = sr.uri || bp.uri;
433
+ return { ...bp, id: sr.id, uri: canonicalUri };
434
+ }
435
+ return bp;
404
436
  });
405
437
  if (_saveBpState) _saveBpState(config, updatedWithServerIds);
406
438
 
@@ -435,7 +467,8 @@ async function cmdSet(args, config, adt) {
435
467
 
436
468
  if (jsonOutput) {
437
469
  const out = added.map(a => {
438
- const sr = serverResults.find(r => r.uri === a.uri && r.line === a.line);
470
+ const sr = serverResults.find(r => r.uri === a.uri && r.line === a.line)
471
+ || serverResults.find(r => r.line === a.line);
439
472
  return { id: (sr && sr.id) || null, object: a.name, line: a.line };
440
473
  });
441
474
  console.log(JSON.stringify(out.length === 1 ? out[0] : out));