@salesforce/source-tracking 1.3.0 → 1.3.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/CHANGELOG.md CHANGED
@@ -2,6 +2,12 @@
2
2
 
3
3
  All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
4
4
 
5
+ ### [1.3.1](https://github.com/forcedotcom/source-tracking/compare/v1.3.0...v1.3.1) (2022-03-25)
6
+
7
+ ### Bug Fixes
8
+
9
+ - tracking really large repos in chunks, lower limit for windows ([0cb2ce5](https://github.com/forcedotcom/source-tracking/commit/0cb2ce5f3b65b8be9f4e4210aba010e919f692a3))
10
+
5
11
  ## [1.3.0](https://github.com/forcedotcom/source-tracking/compare/v1.2.0...v1.3.0) (2022-03-25)
6
12
 
7
13
  ### Features
@@ -8,3 +8,4 @@ export declare const isBundle: (cmp: SourceComponent) => boolean;
8
8
  * ex: '/foo/bar-extra/baz'.startsWith('foo/bar') would be true, but this function understands that they are not in the same folder
9
9
  */
10
10
  export declare const pathIsInFolder: (filePath: string, folder: string) => boolean;
11
+ export declare const chunkArray: <T>(arr: T[], size: number) => T[][];
@@ -6,7 +6,7 @@
6
6
  * For full license text, see LICENSE.txt file in the repo root or https://opensource.org/licenses/BSD-3-Clause
7
7
  */
8
8
  Object.defineProperty(exports, "__esModule", { value: true });
9
- exports.pathIsInFolder = exports.isBundle = exports.getKeyFromObject = exports.getMetadataKey = void 0;
9
+ exports.chunkArray = exports.pathIsInFolder = exports.isBundle = exports.getKeyFromObject = exports.getMetadataKey = void 0;
10
10
  const path_1 = require("path");
11
11
  const ts_types_1 = require("@salesforce/ts-types");
12
12
  const getMetadataKey = (metadataType, metadataName) => {
@@ -37,4 +37,7 @@ exports.pathIsInFolder = pathIsInFolder;
37
37
  const nonEmptyStringFilter = (value) => {
38
38
  return (0, ts_types_1.isString)(value) && value.length > 0;
39
39
  };
40
+ // adapted for TS from https://github.com/30-seconds/30-seconds-of-code/blob/master/snippets/chunk.md
41
+ const chunkArray = (arr, size) => Array.from({ length: Math.ceil(arr.length / size) }, (v, i) => arr.slice(i * size, i * size + size));
42
+ exports.chunkArray = chunkArray;
40
43
  //# sourceMappingURL=functions.js.map
@@ -18,6 +18,9 @@ export declare class ShadowRepo {
18
18
  private packageDirs;
19
19
  private status;
20
20
  private logger;
21
+ private isWindows;
22
+ /** do not try to add more than this many files at a time through isogit. You'll hit EMFILE: too many open files even with graceful-fs */
23
+ private maxFileAdd;
21
24
  private constructor();
22
25
  static getInstance(options: ShadowRepoOptions): Promise<ShadowRepo>;
23
26
  init(): Promise<void>;
@@ -13,10 +13,7 @@ const fs = require("graceful-fs");
13
13
  const core_1 = require("@salesforce/core");
14
14
  const git = require("isomorphic-git");
15
15
  const functions_1 = require("./functions");
16
- const gitIgnoreFileName = '.gitignore';
17
- /**
18
- * returns the full path to where we store the shadow repo
19
- */
16
+ /** returns the full path to where we store the shadow repo */
20
17
  const getGitDir = (orgId, projectPath) => {
21
18
  return path.join(projectPath, '.sfdx', 'orgs', orgId, 'localSourceTracking');
22
19
  };
@@ -31,6 +28,8 @@ class ShadowRepo {
31
28
  this.gitDir = getGitDir(options.orgId, options.projectPath);
32
29
  this.projectPath = options.projectPath;
33
30
  this.packageDirs = options.packageDirs;
31
+ this.isWindows = os.type() === 'Windows_NT';
32
+ this.maxFileAdd = this.isWindows ? 8000 : 15000;
34
33
  }
35
34
  // think of singleton behavior but unique to the projectPath
36
35
  static async getInstance(options) {
@@ -82,14 +81,12 @@ class ShadowRepo {
82
81
  */
83
82
  async getStatus(noCache = false) {
84
83
  if (!this.status || noCache) {
85
- // only ask about OS once but use twice
86
- const isWindows = os.type() === 'Windows_NT';
87
84
  // iso-git uses relative, posix paths
88
85
  // but packageDirs has already resolved / normalized them
89
86
  // so we need to make them project-relative again and convert if windows
90
87
  const filepaths = this.packageDirs
91
88
  .map((dir) => path.relative(this.projectPath, dir.fullPath))
92
- .map((p) => (isWindows ? p.split(path.sep).join(path.posix.sep) : p));
89
+ .map((p) => (this.isWindows ? p.split(path.sep).join(path.posix.sep) : p));
93
90
  // status hasn't been initalized yet
94
91
  this.status = await git.statusMatrix({
95
92
  fs,
@@ -103,12 +100,12 @@ class ShadowRepo {
103
100
  // no lwc tests
104
101
  !f.includes('__tests__') &&
105
102
  // no gitignore files
106
- !f.endsWith(gitIgnoreFileName) &&
103
+ !f.endsWith('.gitignore') &&
107
104
  // isogit uses `startsWith` for filepaths so it's possible to get a false positive
108
105
  filepaths.some((pkgDir) => (0, functions_1.pathIsInFolder)(f, pkgDir)),
109
106
  });
110
107
  // isomorphic-git stores things in unix-style tree. Convert to windows-style if necessary
111
- if (isWindows) {
108
+ if (this.isWindows) {
112
109
  this.status = this.status.map((row) => [path.normalize(row[FILE]), row[HEAD], row[WORKDIR], row[3]]);
113
110
  }
114
111
  }
@@ -179,13 +176,27 @@ class ShadowRepo {
179
176
  deletedFiles = deletedFiles.map((filepath) => path.normalize(filepath).split(path.sep).join(path.posix.sep));
180
177
  }
181
178
  if (deployedFiles.length) {
182
- await git.add({
183
- fs,
184
- dir: this.projectPath,
185
- gitdir: this.gitDir,
186
- filepath: [...new Set(deployedFiles)],
187
- force: true,
188
- });
179
+ const chunks = (0, functions_1.chunkArray)([...new Set(deployedFiles)], this.maxFileAdd);
180
+ for (const chunk of chunks) {
181
+ try {
182
+ await git.add({
183
+ fs,
184
+ dir: this.projectPath,
185
+ gitdir: this.gitDir,
186
+ filepath: chunk,
187
+ force: true,
188
+ });
189
+ }
190
+ catch (e) {
191
+ if (e instanceof git.Errors.MultipleGitError) {
192
+ this.logger.error('multiple errors on git.add', e.errors.slice(0, 5));
193
+ const error = new core_1.SfdxError(e.message, e.name, [], 1);
194
+ error.setData(e.errors);
195
+ throw error;
196
+ }
197
+ throw e;
198
+ }
199
+ }
189
200
  }
190
201
  for (const filepath of [...new Set(deletedFiles)]) {
191
202
  await git.remove({ fs, dir: this.projectPath, gitdir: this.gitDir, filepath });
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@salesforce/source-tracking",
3
3
  "description": "API for tracking local and remote Salesforce metadata changes",
4
- "version": "1.3.0",
4
+ "version": "1.3.1",
5
5
  "author": "Salesforce",
6
6
  "license": "BSD-3-Clause",
7
7
  "main": "lib/index.js",
@@ -47,7 +47,7 @@
47
47
  "@salesforce/kit": "^1.5.17",
48
48
  "@salesforce/source-deploy-retrieve": "^5.9.4",
49
49
  "graceful-fs": "^4.2.9",
50
- "isomorphic-git": "1.16.0",
50
+ "isomorphic-git": "1.17.0",
51
51
  "ts-retry-promise": "^0.6.0"
52
52
  },
53
53
  "devDependencies": {