gtx-cli 2.6.7 → 2.6.8
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/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,14 @@
|
|
|
1
1
|
# gtx-cli
|
|
2
2
|
|
|
3
|
+
## 2.6.8
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- [#981](https://github.com/generaltranslation/gt/pull/981) [`fca3a25`](https://github.com/generaltranslation/gt/commit/fca3a2583eb7f21bc3ef13516351d479f7bef882) Thanks [@fernando-aviles](https://github.com/fernando-aviles)! - Handling source file movement to persist existing translations instead of retranslating
|
|
8
|
+
|
|
9
|
+
- Updated dependencies [[`fca3a25`](https://github.com/generaltranslation/gt/commit/fca3a2583eb7f21bc3ef13516351d479f7bef882)]:
|
|
10
|
+
- generaltranslation@8.1.8
|
|
11
|
+
|
|
3
12
|
## 2.6.7
|
|
4
13
|
|
|
5
14
|
### Patch Changes
|
|
@@ -136,12 +136,14 @@ export async function aggregateFiles(settings) {
|
|
|
136
136
|
addedMintlifyTitle = result.addedTitle;
|
|
137
137
|
}
|
|
138
138
|
const sanitizedContent = sanitizeFileContent(processedContent);
|
|
139
|
+
// Always hash original content for versionId
|
|
140
|
+
const computedVersionId = hashStringSync(content);
|
|
139
141
|
return {
|
|
140
142
|
content: sanitizedContent,
|
|
141
143
|
fileName: relativePath,
|
|
142
144
|
fileFormat: fileType.toUpperCase(),
|
|
143
145
|
fileId: hashStringSync(relativePath),
|
|
144
|
-
versionId:
|
|
146
|
+
versionId: computedVersionId,
|
|
145
147
|
locale: settings.defaultLocale,
|
|
146
148
|
};
|
|
147
149
|
})
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const PACKAGE_VERSION = "2.6.
|
|
1
|
+
export declare const PACKAGE_VERSION = "2.6.8";
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
// This file is auto-generated. Do not edit manually.
|
|
2
|
-
export const PACKAGE_VERSION = '2.6.
|
|
2
|
+
export const PACKAGE_VERSION = '2.6.8';
|
|
@@ -13,6 +13,12 @@ export declare class UploadSourcesStep extends WorkflowStep<{
|
|
|
13
13
|
private spinner;
|
|
14
14
|
private result;
|
|
15
15
|
constructor(gt: GT, settings: Settings);
|
|
16
|
+
/**
|
|
17
|
+
* Detects file moves by comparing local files against orphaned files.
|
|
18
|
+
* A move is detected when a local file has the same versionId (content hash)
|
|
19
|
+
* as an orphaned file but a different fileId (path hash).
|
|
20
|
+
*/
|
|
21
|
+
private detectMoves;
|
|
16
22
|
run({ files, branchData, }: {
|
|
17
23
|
files: FileToUpload[];
|
|
18
24
|
branchData: BranchData;
|
|
@@ -11,21 +11,70 @@ export class UploadSourcesStep extends WorkflowStep {
|
|
|
11
11
|
this.gt = gt;
|
|
12
12
|
this.settings = settings;
|
|
13
13
|
}
|
|
14
|
+
/**
|
|
15
|
+
* Detects file moves by comparing local files against orphaned files.
|
|
16
|
+
* A move is detected when a local file has the same versionId (content hash)
|
|
17
|
+
* as an orphaned file but a different fileId (path hash).
|
|
18
|
+
*/
|
|
19
|
+
detectMoves(localFiles, orphanedFiles) {
|
|
20
|
+
const moves = [];
|
|
21
|
+
// Build a map of versionId -> orphaned file
|
|
22
|
+
const orphansByVersionId = new Map();
|
|
23
|
+
for (const orphan of orphanedFiles) {
|
|
24
|
+
orphansByVersionId.set(orphan.versionId, orphan);
|
|
25
|
+
}
|
|
26
|
+
// Check each local file against orphaned files
|
|
27
|
+
for (const local of localFiles) {
|
|
28
|
+
const orphan = orphansByVersionId.get(local.versionId);
|
|
29
|
+
if (orphan && orphan.fileId !== local.fileId) {
|
|
30
|
+
// Same content, different path = move detected
|
|
31
|
+
moves.push({
|
|
32
|
+
oldFileId: orphan.fileId,
|
|
33
|
+
newFileId: local.fileId,
|
|
34
|
+
newFileName: local.fileName,
|
|
35
|
+
});
|
|
36
|
+
// Remove from map to avoid matching same orphan twice
|
|
37
|
+
orphansByVersionId.delete(local.versionId);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
return moves;
|
|
41
|
+
}
|
|
14
42
|
async run({ files, branchData, }) {
|
|
15
43
|
if (files.length === 0) {
|
|
16
44
|
logger.info('No files to upload found... skipping upload step');
|
|
17
45
|
return [];
|
|
18
46
|
}
|
|
47
|
+
const currentBranchId = branchData.currentBranch.id;
|
|
19
48
|
this.spinner.start(`Syncing ${files.length} file${files.length !== 1 ? 's' : ''} with General Translation API...`);
|
|
20
|
-
//
|
|
21
|
-
const fileData = await
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
49
|
+
// Query file data and orphaned files in parallel
|
|
50
|
+
const [fileData, orphanedFilesResult] = await Promise.all([
|
|
51
|
+
this.gt.queryFileData({
|
|
52
|
+
sourceFiles: files.map((f) => ({
|
|
53
|
+
fileId: f.fileId,
|
|
54
|
+
versionId: f.versionId,
|
|
55
|
+
branchId: f.branchId ?? currentBranchId,
|
|
56
|
+
})),
|
|
57
|
+
}),
|
|
58
|
+
this.gt.getOrphanedFiles(currentBranchId, files.map((f) => f.fileId)),
|
|
59
|
+
]);
|
|
60
|
+
// Detect file moves
|
|
61
|
+
const moves = this.detectMoves(files, orphanedFilesResult.orphanedFiles);
|
|
62
|
+
// Track successfully moved files
|
|
63
|
+
let successfullyMovedFileIds = new Set();
|
|
64
|
+
// Process moves if any were detected
|
|
65
|
+
if (moves.length > 0) {
|
|
66
|
+
this.spinner.message(`Detected ${moves.length} moved file${moves.length !== 1 ? 's' : ''}, preserving translations...`);
|
|
67
|
+
const moveResult = await this.gt.processFileMoves(moves, {
|
|
68
|
+
branchId: currentBranchId,
|
|
69
|
+
});
|
|
70
|
+
// Only track files where the move actually succeeded
|
|
71
|
+
successfullyMovedFileIds = new Set(moveResult.results.filter((r) => r.success).map((r) => r.newFileId));
|
|
72
|
+
const failed = moveResult.summary.failed;
|
|
73
|
+
if (failed > 0) {
|
|
74
|
+
logger.warn(`Failed to migrate ${failed} moved file${failed !== 1 ? 's' : ''}`);
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
// Build a map of branch:fileId:versionId to fileData
|
|
29
78
|
const fileDataMap = new Map();
|
|
30
79
|
fileData.sourceFiles?.forEach((f) => {
|
|
31
80
|
fileDataMap.set(`${f.branchId}:${f.fileId}:${f.versionId}`, f);
|
|
@@ -34,7 +83,8 @@ export class UploadSourcesStep extends WorkflowStep {
|
|
|
34
83
|
const filesToUpload = [];
|
|
35
84
|
const filesToSkipUpload = [];
|
|
36
85
|
files.forEach((f) => {
|
|
37
|
-
|
|
86
|
+
const key = `${f.branchId ?? currentBranchId}:${f.fileId}:${f.versionId}`;
|
|
87
|
+
if (fileDataMap.has(key) || successfullyMovedFileIds.has(f.fileId)) {
|
|
38
88
|
filesToSkipUpload.push(f);
|
|
39
89
|
}
|
|
40
90
|
else {
|
|
@@ -44,7 +94,7 @@ export class UploadSourcesStep extends WorkflowStep {
|
|
|
44
94
|
const response = await this.gt.uploadSourceFiles(filesToUpload.map((f) => ({
|
|
45
95
|
source: {
|
|
46
96
|
...f,
|
|
47
|
-
branchId: f.branchId ??
|
|
97
|
+
branchId: f.branchId ?? currentBranchId,
|
|
48
98
|
locale: this.settings.defaultLocale,
|
|
49
99
|
incomingBranchId: branchData.incomingBranch?.id,
|
|
50
100
|
checkedOutBranchId: branchData.checkedOutBranch?.id,
|
|
@@ -58,13 +108,14 @@ export class UploadSourcesStep extends WorkflowStep {
|
|
|
58
108
|
this.result.push(...filesToSkipUpload.map((f) => ({
|
|
59
109
|
fileId: f.fileId,
|
|
60
110
|
versionId: f.versionId,
|
|
61
|
-
branchId: f.branchId ??
|
|
111
|
+
branchId: f.branchId ?? currentBranchId,
|
|
62
112
|
fileName: f.fileName,
|
|
63
113
|
fileFormat: f.fileFormat,
|
|
64
114
|
dataFormat: f.dataFormat,
|
|
65
115
|
locale: f.locale,
|
|
66
116
|
})));
|
|
67
|
-
|
|
117
|
+
const moveMsg = moves.length > 0 ? ` (${moves.length} moved)` : '';
|
|
118
|
+
this.spinner.stop(chalk.green(`Files uploaded successfully${moveMsg}`));
|
|
68
119
|
return this.result;
|
|
69
120
|
}
|
|
70
121
|
async wait() {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "gtx-cli",
|
|
3
|
-
"version": "2.6.
|
|
3
|
+
"version": "2.6.8",
|
|
4
4
|
"main": "dist/index.js",
|
|
5
5
|
"bin": "dist/main.js",
|
|
6
6
|
"files": [
|
|
@@ -106,7 +106,7 @@
|
|
|
106
106
|
"unified": "^11.0.5",
|
|
107
107
|
"unist-util-visit": "^5.0.0",
|
|
108
108
|
"yaml": "^2.8.0",
|
|
109
|
-
"generaltranslation": "8.1.
|
|
109
|
+
"generaltranslation": "8.1.8"
|
|
110
110
|
},
|
|
111
111
|
"devDependencies": {
|
|
112
112
|
"@babel/types": "^7.28.4",
|