@adobe/aem-cli 16.19.13 → 16.19.14
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 +7 -0
- package/package.json +1 -1
- package/src/content/clone.cmd.js +11 -11
- package/src/content/content-shared.js +25 -0
- package/src/content/da-api.js +20 -17
- package/src/content/diff.cmd.js +3 -8
- package/src/content/merge.cmd.js +3 -8
- package/src/content/push.cmd.js +15 -20
- package/src/content/status.cmd.js +3 -9
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,10 @@
|
|
|
1
|
+
## [16.19.14](https://github.com/adobe/helix-cli/compare/v16.19.13...v16.19.14) (2026-06-04)
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
### Bug Fixes
|
|
5
|
+
|
|
6
|
+
* **content:** use org/site terminology and centralize config reading ([#2737](https://github.com/adobe/helix-cli/issues/2737)) ([bb0d357](https://github.com/adobe/helix-cli/commit/bb0d35744b41487245c269de6000a0d9a23d5bdb))
|
|
7
|
+
|
|
1
8
|
## [16.19.13](https://github.com/adobe/helix-cli/compare/v16.19.12...v16.19.13) (2026-06-03)
|
|
2
9
|
|
|
3
10
|
|
package/package.json
CHANGED
package/src/content/clone.cmd.js
CHANGED
|
@@ -101,14 +101,14 @@ export default class CloneCommand {
|
|
|
101
101
|
throw new Error('Clone root path was not set (internal error).');
|
|
102
102
|
}
|
|
103
103
|
|
|
104
|
-
// 1. Resolve
|
|
104
|
+
// 1. Resolve org/site from git remote (GitHub owner/repo → da.live org/site)
|
|
105
105
|
const originUrl = await GitUtils.getOriginURL(this._dir);
|
|
106
106
|
if (!originUrl) {
|
|
107
107
|
throw new Error('No git remote found. Run `aem content clone` inside an AEM project directory.');
|
|
108
108
|
}
|
|
109
|
-
const
|
|
110
|
-
const
|
|
111
|
-
log.info(`Cloning content from da.live: ${
|
|
109
|
+
const org = originUrl.owner.toLowerCase();
|
|
110
|
+
const site = originUrl.repo.toLowerCase();
|
|
111
|
+
log.info(`Cloning content from da.live: ${org}/${site}${this._rootPath === '/' ? '' : ` @ ${this._rootPath}`}`);
|
|
112
112
|
|
|
113
113
|
// 2. Ensure target path is available (do not create content/ until after file count is known)
|
|
114
114
|
const contentDir = path.resolve(this._dir, CONTENT_DIR);
|
|
@@ -126,7 +126,7 @@ export default class CloneCommand {
|
|
|
126
126
|
const client = new DaClient(token);
|
|
127
127
|
log.info('Fetching file list...');
|
|
128
128
|
const showDiscoveryProgress = process.stdout.isTTY;
|
|
129
|
-
const files = await client.listAll(
|
|
129
|
+
const files = await client.listAll(org, site, this._rootPath, showDiscoveryProgress
|
|
130
130
|
? (n) => {
|
|
131
131
|
process.stdout.write(`\r ${n} file(s) discovered so far...`);
|
|
132
132
|
}
|
|
@@ -148,15 +148,15 @@ export default class CloneCommand {
|
|
|
148
148
|
const downloadResults = await processQueue(
|
|
149
149
|
files,
|
|
150
150
|
async (file) => {
|
|
151
|
-
const prefix = `/${
|
|
151
|
+
const prefix = `/${org}/${site}`;
|
|
152
152
|
if (!file.path.startsWith(prefix)) {
|
|
153
|
-
log.warn(` skip (unexpected path, missing
|
|
153
|
+
log.warn(` skip (unexpected path, missing org/site prefix): ${file.path}`);
|
|
154
154
|
return { status: 404 };
|
|
155
155
|
}
|
|
156
156
|
const daPath = file.path.slice(prefix.length) || '/';
|
|
157
157
|
const localPath = path.join(contentDir, ...daPath.split('/').filter(Boolean));
|
|
158
158
|
try {
|
|
159
|
-
const res = await client.getSource(
|
|
159
|
+
const res = await client.getSource(org, site, daPath);
|
|
160
160
|
if (!res) {
|
|
161
161
|
log.warn(` skip (not found): ${daPath}`);
|
|
162
162
|
return { status: 404 };
|
|
@@ -195,7 +195,7 @@ export default class CloneCommand {
|
|
|
195
195
|
await git.commit({
|
|
196
196
|
fs,
|
|
197
197
|
dir: contentDir,
|
|
198
|
-
message: `clone: ${
|
|
198
|
+
message: `clone: ${org}/${site}${this._rootPath === '/' ? '' : ` (${this._rootPath})`}`,
|
|
199
199
|
author: GIT_AUTHOR,
|
|
200
200
|
});
|
|
201
201
|
const headOid = await git.resolveRef({ fs, dir: contentDir, ref: 'HEAD' });
|
|
@@ -203,8 +203,8 @@ export default class CloneCommand {
|
|
|
203
203
|
|
|
204
204
|
// 8. Write config (not tracked by git)
|
|
205
205
|
await fse.writeJson(path.join(contentDir, CONFIG_FILE), {
|
|
206
|
-
|
|
207
|
-
|
|
206
|
+
org,
|
|
207
|
+
site,
|
|
208
208
|
rootPath: this._rootPath,
|
|
209
209
|
}, { spaces: 2 });
|
|
210
210
|
|
|
@@ -10,6 +10,9 @@
|
|
|
10
10
|
* governing permissions and limitations under the License.
|
|
11
11
|
*/
|
|
12
12
|
|
|
13
|
+
import path from 'path';
|
|
14
|
+
import fse from 'fs-extra';
|
|
15
|
+
|
|
13
16
|
export const CONTENT_DIR = 'content';
|
|
14
17
|
export const CONFIG_FILE = '.da-config.json';
|
|
15
18
|
export const GIT_AUTHOR = { name: 'aem-cli', email: 'aem-cli@adobe.com' };
|
|
@@ -22,6 +25,28 @@ export const LARGE_CLONE_FILE_THRESHOLD = 10000;
|
|
|
22
25
|
*/
|
|
23
26
|
export const CONTENT_IO_CONCURRENCY = 10;
|
|
24
27
|
|
|
28
|
+
/**
|
|
29
|
+
* Reads and normalizes the content config from a content directory.
|
|
30
|
+
* Accepts both current keys (org/site) and legacy keys (owner/repo) written
|
|
31
|
+
* by earlier versions of clone. org/site take priority when both are present.
|
|
32
|
+
* @param {string} contentDir - absolute path to the content/ directory
|
|
33
|
+
* @returns {Promise<{org: string, site: string, rootPath: string|undefined}>}
|
|
34
|
+
* @throws if the config file is missing or org/site cannot be resolved
|
|
35
|
+
*/
|
|
36
|
+
export async function readContentConfig(contentDir) {
|
|
37
|
+
const configPath = path.join(contentDir, CONFIG_FILE);
|
|
38
|
+
if (!await fse.pathExists(configPath)) {
|
|
39
|
+
throw new Error(`No config found at ${configPath}. Run 'aem content clone' first.`);
|
|
40
|
+
}
|
|
41
|
+
const raw = await fse.readJson(configPath);
|
|
42
|
+
const org = (raw.org || raw.owner || '').toLowerCase();
|
|
43
|
+
const site = (raw.site || raw.repo || '').toLowerCase();
|
|
44
|
+
if (!org || !site) {
|
|
45
|
+
throw new Error(`Invalid config: org and site are required in ${configPath}.`);
|
|
46
|
+
}
|
|
47
|
+
return { org, site, rootPath: raw.rootPath };
|
|
48
|
+
}
|
|
49
|
+
|
|
25
50
|
/**
|
|
26
51
|
* Normalizes a da.live path: leading slash, no trailing slash except root.
|
|
27
52
|
* @param {string} input
|
package/src/content/da-api.js
CHANGED
|
@@ -39,12 +39,12 @@ export class DaClient {
|
|
|
39
39
|
/**
|
|
40
40
|
* Lists the contents of a directory, following {@link LIST_CONTINUATION_HEADER} until complete.
|
|
41
41
|
* @param {string} org
|
|
42
|
-
* @param {string}
|
|
42
|
+
* @param {string} site
|
|
43
43
|
* @param {string} daPath - path starting with /
|
|
44
44
|
* @returns {Promise<Array<{path, name, ext?, lastModified}>>}
|
|
45
45
|
*/
|
|
46
|
-
async list(org,
|
|
47
|
-
const url = `${DA_ADMIN}/list/${org}/${
|
|
46
|
+
async list(org, site, daPath) {
|
|
47
|
+
const url = `${DA_ADMIN}/list/${org}/${site}${daPath}`;
|
|
48
48
|
const aggregated = [];
|
|
49
49
|
let continuation = null;
|
|
50
50
|
|
|
@@ -81,13 +81,13 @@ export class DaClient {
|
|
|
81
81
|
/**
|
|
82
82
|
* Recursively lists all files under a path using a non-recursive queue-based approach.
|
|
83
83
|
* @param {string} org
|
|
84
|
-
* @param {string}
|
|
84
|
+
* @param {string} site
|
|
85
85
|
* @param {string} [daPath='/']
|
|
86
86
|
* @param {(discoveredCount: number) => void} [onDiscovered] - cumulative file count per discovery
|
|
87
87
|
* @returns {Promise<Array<{path, name, ext, lastModified}>>}
|
|
88
88
|
*/
|
|
89
|
-
async listAll(org,
|
|
90
|
-
const prefix = `/${org}/${
|
|
89
|
+
async listAll(org, site, daPath = '/', onDiscovered = undefined) {
|
|
90
|
+
const prefix = `/${org}/${site}`;
|
|
91
91
|
const files = [];
|
|
92
92
|
let dirsToProcess = [daPath];
|
|
93
93
|
|
|
@@ -97,7 +97,7 @@ export class DaClient {
|
|
|
97
97
|
await processQueue(
|
|
98
98
|
dirsToProcess,
|
|
99
99
|
async (currentPath) => {
|
|
100
|
-
const items = await this.list(org,
|
|
100
|
+
const items = await this.list(org, site, currentPath);
|
|
101
101
|
for (const item of items) {
|
|
102
102
|
if (item.ext !== undefined) {
|
|
103
103
|
files.push(item);
|
|
@@ -119,10 +119,13 @@ export class DaClient {
|
|
|
119
119
|
|
|
120
120
|
/**
|
|
121
121
|
* Fetches the raw content of a file.
|
|
122
|
+
* @param {string} org
|
|
123
|
+
* @param {string} site
|
|
124
|
+
* @param {string} daPath
|
|
122
125
|
* @returns {Promise<Response|null>}
|
|
123
126
|
*/
|
|
124
|
-
async getSource(org,
|
|
125
|
-
const url = `${DA_ADMIN}/source/${org}/${
|
|
127
|
+
async getSource(org, site, daPath) {
|
|
128
|
+
const url = `${DA_ADMIN}/source/${org}/${site}${daPath}`;
|
|
126
129
|
const res = await this.fetch(url, { headers: this.authHeader });
|
|
127
130
|
if (res.status === 401) {
|
|
128
131
|
throw new Error('Unauthorized: invalid or missing token');
|
|
@@ -139,14 +142,14 @@ export class DaClient {
|
|
|
139
142
|
/**
|
|
140
143
|
* Uploads a file via PUT.
|
|
141
144
|
* @param {string} org
|
|
142
|
-
* @param {string}
|
|
145
|
+
* @param {string} site
|
|
143
146
|
* @param {string} daPath
|
|
144
147
|
* @param {Buffer} buffer
|
|
145
148
|
* @param {string} contentType
|
|
146
149
|
* @returns {Promise<object>} API response body
|
|
147
150
|
*/
|
|
148
|
-
async putSource(org,
|
|
149
|
-
const url = `${DA_ADMIN}/source/${org}/${
|
|
151
|
+
async putSource(org, site, daPath, buffer, contentType) {
|
|
152
|
+
const url = `${DA_ADMIN}/source/${org}/${site}${daPath}`;
|
|
150
153
|
const res = await this.fetch(url, {
|
|
151
154
|
method: 'PUT',
|
|
152
155
|
headers: { ...this.authHeader, 'Content-Type': contentType },
|
|
@@ -165,8 +168,8 @@ export class DaClient {
|
|
|
165
168
|
* Deletes a file or folder. Idempotent: 404 is treated as success.
|
|
166
169
|
* Throws on transport or server errors so callers don't silently treat them as success.
|
|
167
170
|
*/
|
|
168
|
-
async deleteSource(org,
|
|
169
|
-
const url = `${DA_ADMIN}/source/${org}/${
|
|
171
|
+
async deleteSource(org, site, daPath) {
|
|
172
|
+
const url = `${DA_ADMIN}/source/${org}/${site}${daPath}`;
|
|
170
173
|
const res = await this.fetch(url, {
|
|
171
174
|
method: 'DELETE',
|
|
172
175
|
headers: this.authHeader,
|
|
@@ -183,12 +186,12 @@ export class DaClient {
|
|
|
183
186
|
/**
|
|
184
187
|
* Returns the current lastModified for a file via a HEAD request.
|
|
185
188
|
* @param {string} org
|
|
186
|
-
* @param {string}
|
|
189
|
+
* @param {string} site
|
|
187
190
|
* @param {string} daPath - e.g. /blog/post.html
|
|
188
191
|
* @returns {Promise<number|null>}
|
|
189
192
|
*/
|
|
190
|
-
async getRemoteLastModified(org,
|
|
191
|
-
const url = `${DA_ADMIN}/source/${org}/${
|
|
193
|
+
async getRemoteLastModified(org, site, daPath) {
|
|
194
|
+
const url = `${DA_ADMIN}/source/${org}/${site}${daPath}`;
|
|
192
195
|
const res = await this.fetch(url, { method: 'HEAD', headers: this.authHeader });
|
|
193
196
|
if (res.status === 401) {
|
|
194
197
|
throw new Error('Unauthorized: invalid or missing token');
|
package/src/content/diff.cmd.js
CHANGED
|
@@ -17,7 +17,7 @@ import { createTwoFilesPatch } from 'diff';
|
|
|
17
17
|
import chalk from 'chalk-template';
|
|
18
18
|
import { DaClient } from './da-api.js';
|
|
19
19
|
import { getValidToken } from './da-auth.js';
|
|
20
|
-
import { CONTENT_DIR,
|
|
20
|
+
import { CONTENT_DIR, readContentConfig } from './content-shared.js';
|
|
21
21
|
|
|
22
22
|
function printPatch(patch) {
|
|
23
23
|
for (const line of patch.split('\n')) {
|
|
@@ -60,12 +60,7 @@ export default class DiffCommand {
|
|
|
60
60
|
async run() {
|
|
61
61
|
const { log } = this;
|
|
62
62
|
const contentDir = path.resolve(this._dir, CONTENT_DIR);
|
|
63
|
-
const
|
|
64
|
-
|
|
65
|
-
if (!await fse.pathExists(configPath)) {
|
|
66
|
-
throw new Error('No config found. Run \'aem content clone\' first.');
|
|
67
|
-
}
|
|
68
|
-
const { org, repo } = await fse.readJson(configPath);
|
|
63
|
+
const { org, site } = await readContentConfig(contentDir);
|
|
69
64
|
|
|
70
65
|
const matrix = await git.statusMatrix({ fs, dir: contentDir });
|
|
71
66
|
let changedPaths = matrix
|
|
@@ -98,7 +93,7 @@ export default class DiffCommand {
|
|
|
98
93
|
? await fse.readFile(localPath)
|
|
99
94
|
: Buffer.from('');
|
|
100
95
|
|
|
101
|
-
const remoteRes = await client.getSource(org,
|
|
96
|
+
const remoteRes = await client.getSource(org, site, daPath);
|
|
102
97
|
|
|
103
98
|
const localText = localBuffer.toString('utf-8');
|
|
104
99
|
const remoteText = remoteRes ? await remoteRes.text() : '';
|
package/src/content/merge.cmd.js
CHANGED
|
@@ -16,7 +16,7 @@ import git from 'isomorphic-git';
|
|
|
16
16
|
import { diff3Merge } from 'node-diff3'; // eslint-disable-line import/no-unresolved
|
|
17
17
|
import { DaClient } from './da-api.js';
|
|
18
18
|
import { getValidToken } from './da-auth.js';
|
|
19
|
-
import { CONTENT_DIR,
|
|
19
|
+
import { CONTENT_DIR, readContentConfig } from './content-shared.js';
|
|
20
20
|
|
|
21
21
|
/**
|
|
22
22
|
* 3-way merge using diff3 algorithm.
|
|
@@ -69,12 +69,7 @@ export default class MergeCommand {
|
|
|
69
69
|
async run() {
|
|
70
70
|
const { log } = this;
|
|
71
71
|
const contentDir = path.resolve(this._dir, CONTENT_DIR);
|
|
72
|
-
const
|
|
73
|
-
|
|
74
|
-
if (!await fse.pathExists(configPath)) {
|
|
75
|
-
throw new Error('No config found. Run \'aem content clone\' first.');
|
|
76
|
-
}
|
|
77
|
-
const { org, repo } = await fse.readJson(configPath);
|
|
72
|
+
const { org, site } = await readContentConfig(contentDir);
|
|
78
73
|
|
|
79
74
|
// Find locally changed files via git
|
|
80
75
|
const matrix = await git.statusMatrix({ fs, dir: contentDir });
|
|
@@ -112,7 +107,7 @@ export default class MergeCommand {
|
|
|
112
107
|
// eslint-disable-next-line no-await-in-loop
|
|
113
108
|
const [localBuffer, remoteRes, blobResult] = await Promise.all([
|
|
114
109
|
fse.readFile(localPath),
|
|
115
|
-
client.getSource(org,
|
|
110
|
+
client.getSource(org, site, daPath),
|
|
116
111
|
git.readBlob({
|
|
117
112
|
fs, dir: contentDir, oid: headCommit.oid, filepath: relPath,
|
|
118
113
|
})
|
package/src/content/push.cmd.js
CHANGED
|
@@ -18,8 +18,8 @@ import { DaClient, getContentType } from './da-api.js';
|
|
|
18
18
|
import { getValidToken } from './da-auth.js';
|
|
19
19
|
import {
|
|
20
20
|
CONTENT_DIR,
|
|
21
|
-
CONFIG_FILE,
|
|
22
21
|
CONTENT_IO_CONCURRENCY,
|
|
22
|
+
readContentConfig,
|
|
23
23
|
} from './content-shared.js';
|
|
24
24
|
import {
|
|
25
25
|
resolveSyncedOid,
|
|
@@ -67,19 +67,19 @@ export default class PushCommand {
|
|
|
67
67
|
* Checks for conflicts between local changes and remote modifications.
|
|
68
68
|
* @param {DaClient} client
|
|
69
69
|
* @param {string} org
|
|
70
|
-
* @param {string}
|
|
70
|
+
* @param {string} site
|
|
71
71
|
* @param {string[]} modified
|
|
72
72
|
* @param {string[]} deleted
|
|
73
73
|
* @param {number} lastSyncTime
|
|
74
74
|
* @returns {Promise<boolean>} true if the push should be aborted
|
|
75
75
|
*/
|
|
76
|
-
async _checkConflicts(client, org,
|
|
76
|
+
async _checkConflicts(client, org, site, modified, deleted, lastSyncTime) {
|
|
77
77
|
const { log } = this;
|
|
78
78
|
const conflicts = [];
|
|
79
79
|
|
|
80
80
|
for (const daPath of [...modified, ...deleted]) {
|
|
81
81
|
// eslint-disable-next-line no-await-in-loop
|
|
82
|
-
const remoteLastModified = await client.getRemoteLastModified(org,
|
|
82
|
+
const remoteLastModified = await client.getRemoteLastModified(org, site, daPath);
|
|
83
83
|
if (remoteLastModified != null && remoteLastModified > lastSyncTime) {
|
|
84
84
|
conflicts.push({ daPath, remoteDate: new Date(remoteLastModified).toLocaleString() });
|
|
85
85
|
}
|
|
@@ -105,12 +105,12 @@ export default class PushCommand {
|
|
|
105
105
|
* Uploads added and modified files to da.live.
|
|
106
106
|
* @param {DaClient} client
|
|
107
107
|
* @param {string} org
|
|
108
|
-
* @param {string}
|
|
108
|
+
* @param {string} site
|
|
109
109
|
* @param {string} contentDir
|
|
110
110
|
* @param {string[]} targets
|
|
111
111
|
* @returns {Promise<{ pushed: number, errors: number }>}
|
|
112
112
|
*/
|
|
113
|
-
async _uploadFiles(client, org,
|
|
113
|
+
async _uploadFiles(client, org, site, contentDir, targets) {
|
|
114
114
|
const { log } = this;
|
|
115
115
|
let pushed = 0;
|
|
116
116
|
let errors = 0;
|
|
@@ -123,7 +123,7 @@ export default class PushCommand {
|
|
|
123
123
|
const ext = daPath.split('.').pop();
|
|
124
124
|
try {
|
|
125
125
|
const buffer = await fse.readFile(localPath);
|
|
126
|
-
await client.putSource(org,
|
|
126
|
+
await client.putSource(org, site, daPath, buffer, getContentType(ext));
|
|
127
127
|
log.info(` ✓ ${daPath}`);
|
|
128
128
|
return { ok: true };
|
|
129
129
|
} catch (err) {
|
|
@@ -148,11 +148,11 @@ export default class PushCommand {
|
|
|
148
148
|
* Deletes files from da.live.
|
|
149
149
|
* @param {DaClient} client
|
|
150
150
|
* @param {string} org
|
|
151
|
-
* @param {string}
|
|
151
|
+
* @param {string} site
|
|
152
152
|
* @param {string[]} deleted
|
|
153
153
|
* @returns {Promise<{ pushed: number, errors: number }>}
|
|
154
154
|
*/
|
|
155
|
-
async _deleteFiles(client, org,
|
|
155
|
+
async _deleteFiles(client, org, site, deleted) {
|
|
156
156
|
const { log } = this;
|
|
157
157
|
let pushed = 0;
|
|
158
158
|
let errors = 0;
|
|
@@ -162,7 +162,7 @@ export default class PushCommand {
|
|
|
162
162
|
[...deleted],
|
|
163
163
|
async (daPath) => {
|
|
164
164
|
try {
|
|
165
|
-
await client.deleteSource(org,
|
|
165
|
+
await client.deleteSource(org, site, daPath);
|
|
166
166
|
log.info(` ✓ deleted ${daPath}`);
|
|
167
167
|
return { ok: true };
|
|
168
168
|
} catch (err) {
|
|
@@ -186,12 +186,7 @@ export default class PushCommand {
|
|
|
186
186
|
async run() {
|
|
187
187
|
const { log } = this;
|
|
188
188
|
const contentDir = path.resolve(this._dir, CONTENT_DIR);
|
|
189
|
-
const
|
|
190
|
-
|
|
191
|
-
if (!await fse.pathExists(configPath)) {
|
|
192
|
-
throw new Error(`No config found at ${configPath}. Run 'aem content clone' first.`);
|
|
193
|
-
}
|
|
194
|
-
const { org, repo } = await fse.readJson(configPath);
|
|
189
|
+
const { org, site } = await readContentConfig(contentDir);
|
|
195
190
|
|
|
196
191
|
const matrix = await git.statusMatrix({ fs, dir: contentDir });
|
|
197
192
|
if (statusMatrixHasUncommitted(matrix)) {
|
|
@@ -228,7 +223,7 @@ export default class PushCommand {
|
|
|
228
223
|
|
|
229
224
|
const token = await getValidToken(log, this._token, this._dir);
|
|
230
225
|
|
|
231
|
-
log.info(`Pushing content to da.live: ${org}/${
|
|
226
|
+
log.info(`Pushing content to da.live: ${org}/${site}`);
|
|
232
227
|
log.info(`${added.length} added, ${modified.length} modified, ${deleted.length} deleted`);
|
|
233
228
|
|
|
234
229
|
const client = new DaClient(token);
|
|
@@ -236,7 +231,7 @@ export default class PushCommand {
|
|
|
236
231
|
const shouldAbort = await this._checkConflicts(
|
|
237
232
|
client,
|
|
238
233
|
org,
|
|
239
|
-
|
|
234
|
+
site,
|
|
240
235
|
modified,
|
|
241
236
|
deleted,
|
|
242
237
|
lastSyncTime,
|
|
@@ -271,12 +266,12 @@ export default class PushCommand {
|
|
|
271
266
|
const {
|
|
272
267
|
pushed: putPushed,
|
|
273
268
|
errors: putErrors,
|
|
274
|
-
} = await this._uploadFiles(client, org,
|
|
269
|
+
} = await this._uploadFiles(client, org, site, contentDir, [...added, ...modified]);
|
|
275
270
|
|
|
276
271
|
const {
|
|
277
272
|
pushed: deletePushed,
|
|
278
273
|
errors: deleteErrors,
|
|
279
|
-
} = await this._deleteFiles(client, org,
|
|
274
|
+
} = await this._deleteFiles(client, org, site, deleted);
|
|
280
275
|
|
|
281
276
|
const pushed = putPushed + deletePushed;
|
|
282
277
|
const pushErrors = putErrors + deleteErrors;
|
|
@@ -11,9 +11,8 @@
|
|
|
11
11
|
*/
|
|
12
12
|
import fs from 'fs';
|
|
13
13
|
import path from 'path';
|
|
14
|
-
import fse from 'fs-extra';
|
|
15
14
|
import git from 'isomorphic-git';
|
|
16
|
-
import { CONTENT_DIR,
|
|
15
|
+
import { CONTENT_DIR, readContentConfig } from './content-shared.js';
|
|
17
16
|
import { resolveSyncedOid, countCommitsAhead } from './content-git.js';
|
|
18
17
|
|
|
19
18
|
export default class StatusCommand {
|
|
@@ -30,14 +29,9 @@ export default class StatusCommand {
|
|
|
30
29
|
async run() {
|
|
31
30
|
const { log } = this;
|
|
32
31
|
const contentDir = path.resolve(this._dir, CONTENT_DIR);
|
|
33
|
-
const
|
|
32
|
+
const { org, site } = await readContentConfig(contentDir);
|
|
34
33
|
|
|
35
|
-
|
|
36
|
-
throw new Error('No config found. Run \'aem content clone\' first.');
|
|
37
|
-
}
|
|
38
|
-
const { org, repo } = await fse.readJson(configPath);
|
|
39
|
-
|
|
40
|
-
log.info(`On da.live: ${org}/${repo}`);
|
|
34
|
+
log.info(`On da.live: ${org}/${site}`);
|
|
41
35
|
log.info(`Local content: ./${CONTENT_DIR}/\n`);
|
|
42
36
|
|
|
43
37
|
const matrix = await git.statusMatrix({ fs, dir: contentDir });
|