From f35178175bf6dba4a1c1311d2c518274266e6403 Mon Sep 17 00:00:00 2001 From: Sebastian Malton Date: Mon, 2 Aug 2021 08:02:55 -0400 Subject: [PATCH] Ignore certain file globs when under dir kube sync (#3452) - .DS_Store - *.lock - *.swp Signed-off-by: Sebastian Malton --- package.json | 2 + src/main/catalog-sources/kubeconfig-sync.ts | 47 ++++++++++++++++++--- yarn.lock | 10 +++++ 3 files changed, 52 insertions(+), 7 deletions(-) diff --git a/package.json b/package.json index ee1bcfc09f..7492cf63a9 100644 --- a/package.json +++ b/package.json @@ -202,6 +202,7 @@ "electron-window-state": "^5.0.3", "filehound": "^1.17.4", "fs-extra": "^9.0.1", + "glob-to-regexp": "^0.4.1", "grapheme-splitter": "^1.0.4", "handlebars": "^4.7.7", "http-proxy": "^1.18.1", @@ -266,6 +267,7 @@ "@types/electron-devtools-installer": "^2.2.0", "@types/electron-window-state": "^2.0.34", "@types/fs-extra": "^9.0.1", + "@types/glob-to-regexp": "^0.4.1", "@types/hapi": "^18.0.6", "@types/hoist-non-react-statics": "^3.3.1", "@types/html-webpack-plugin": "^3.2.3", diff --git a/src/main/catalog-sources/kubeconfig-sync.ts b/src/main/catalog-sources/kubeconfig-sync.ts index e60d9400de..8e3c3b1cf7 100644 --- a/src/main/catalog-sources/kubeconfig-sync.ts +++ b/src/main/catalog-sources/kubeconfig-sync.ts @@ -24,6 +24,7 @@ import type { CatalogEntity } from "../../common/catalog"; import { catalogEntityRegistry } from "../../main/catalog"; import { watch } from "chokidar"; import fs from "fs"; +import path from "path"; import fse from "fs-extra"; import type stream from "stream"; import { Disposer, ExtendedObservableMap, iter, Singleton } from "../../common/utils"; @@ -36,9 +37,23 @@ import { UserStore } from "../../common/user-store"; import { ClusterStore, UpdateClusterModel } from "../../common/cluster-store"; import { createHash } from "crypto"; import { homedir } from "os"; +import globToRegExp from "glob-to-regexp"; +import { inspect } from "util"; const logPrefix = "[KUBECONFIG-SYNC]:"; +/** + * This is the list of globs of which files are ignored when under a folder sync + */ +const ignoreGlobs = [ + "*.lock", // kubectl lock files + "*.swp", // vim swap files + ".DS_Store", // macOS specific +].map(rawGlob => ({ + rawGlob, + matcher: globToRegExp(rawGlob), +})); + export class KubeconfigSyncManager extends Singleton { protected sources = observable.map, Disposer]>(); protected syncing = false; @@ -260,9 +275,10 @@ function diffChangedConfig(filePath: string, source: RootSource): Disposer { async function watchFileChanges(filePath: string): Promise<[IComputedValue, Disposer]> { const stat = await fse.stat(filePath); // traverses symlinks, is a race condition + const isFolderSync = stat.isDirectory(); const watcher = watch(filePath, { followSymlinks: true, - depth: stat.isDirectory() ? 0 : 1, // DIRs works with 0 but files need 1 (bug: https://github.com/paulmillr/chokidar/issues/1095) + depth: isFolderSync ? 0 : 1, // DIRs works with 0 but files need 1 (bug: https://github.com/paulmillr/chokidar/issues/1095) disableGlobbing: true, ignorePermissionErrors: true, usePolling: false, @@ -273,19 +289,36 @@ async function watchFileChanges(filePath: string): Promise<[IComputedValue>(); const derivedSource = computed(() => Array.from(iter.flatMap(rootSource.values(), from => iter.map(from.values(), child => child[1])))); - const stoppers = new Map(); + const cleanupFns = new Map(); watcher .on("change", (childFilePath) => { - stoppers.get(childFilePath)(); - stoppers.set(childFilePath, diffChangedConfig(childFilePath, rootSource.getOrInsert(childFilePath, observable.map))); + const cleanup = cleanupFns.get(childFilePath); + + if (!cleanup) { + // file was previously ignored, do nothing + return void logger.debug(`${logPrefix} ${inspect(childFilePath)} that should have been previously ignored has changed. Doing nothing`); + } + + cleanup(); + cleanupFns.set(childFilePath, diffChangedConfig(childFilePath, rootSource.getOrInsert(childFilePath, observable.map))); }) .on("add", (childFilePath) => { - stoppers.set(childFilePath, diffChangedConfig(childFilePath, rootSource.getOrInsert(childFilePath, observable.map))); + if (isFolderSync) { + const fileName = path.basename(childFilePath); + + for (const ignoreGlob of ignoreGlobs) { + if (ignoreGlob.matcher.test(fileName)) { + return void logger.info(`${logPrefix} ignoring ${inspect(childFilePath)} due to ignore glob: ${ignoreGlob.rawGlob}`); + } + } + } + + cleanupFns.set(childFilePath, diffChangedConfig(childFilePath, rootSource.getOrInsert(childFilePath, observable.map))); }) .on("unlink", (childFilePath) => { - stoppers.get(childFilePath)(); - stoppers.delete(childFilePath); + cleanupFns.get(childFilePath)?.(); + cleanupFns.delete(childFilePath); rootSource.delete(childFilePath); }) .on("error", error => logger.error(`${logPrefix} watching file/folder failed: ${error}`, { filePath })); diff --git a/yarn.lock b/yarn.lock index 3cd9056b43..82396a65f0 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1412,6 +1412,11 @@ dependencies: "@types/node" "*" +"@types/glob-to-regexp@^0.4.1": + version "0.4.1" + resolved "https://registry.yarnpkg.com/@types/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz#f684bc7b9a24691f1f80d045dbb7260bf9cc415b" + integrity sha512-S0mIukll6fbF0tvrKic/jj+jI8SHoSvGU+Cs95b/jzZEnBYCbj+7aJtQ9yeABuK3xP1okwA3jEH9qIRayijnvQ== + "@types/glob@^7.1.1": version "7.1.3" resolved "https://registry.yarnpkg.com/@types/glob/-/glob-7.1.3.tgz#e6ba80f36b7daad2c685acd9266382e68985c183" @@ -6729,6 +6734,11 @@ glob-parent@~5.1.2: dependencies: is-glob "^4.0.1" +glob-to-regexp@^0.4.1: + version "0.4.1" + resolved "https://registry.yarnpkg.com/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz#c75297087c851b9a578bd217dd59a92f59fe546e" + integrity sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw== + glob@^7.0.0, glob@^7.0.3, glob@^7.1.1, glob@^7.1.2, glob@^7.1.3, glob@^7.1.4, glob@^7.1.6, glob@~7.1.1: version "7.1.6" resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.6.tgz#141f33b81a7c2492e125594307480c46679278a6"