From 61b80795a4a5b89db0cebf42a295423e7fc3d2ca Mon Sep 17 00:00:00 2001 From: Elio Date: Thu, 18 Nov 2021 16:24:45 +0100 Subject: [PATCH] #178 - Windows support with PowerShell added --- src/commands/Dashboard.ts | 4 +- src/commands/Folders.ts | 19 +++++-- src/dashboardWebView/hooks/usePages.tsx | 1 - src/helpers/FilesHelper.ts | 66 +++++++++++++++++++++++-- src/helpers/MediaLibrary.ts | 54 +------------------- src/models/PanelSettings.ts | 4 -- 6 files changed, 81 insertions(+), 67 deletions(-) diff --git a/src/commands/Dashboard.ts b/src/commands/Dashboard.ts index e12ab77b..becade2f 100644 --- a/src/commands/Dashboard.ts +++ b/src/commands/Dashboard.ts @@ -3,7 +3,7 @@ import { ArticleHelper } from './../helpers/ArticleHelper'; import { basename, dirname, extname, join, parse } from "path"; import { existsSync, readdirSync, statSync, unlinkSync, writeFileSync } from "fs"; import { commands, Uri, ViewColumn, Webview, WebviewPanel, window, workspace, env, Position } from "vscode"; -import { Settings as SettingsHelper } from '../helpers'; +import { FilesHelper, Settings as SettingsHelper } from '../helpers'; import { DraftField, Framework, SortingSetting, SortOrder, SortType, TaxonomyType } from '../models'; import { Folders } from './Folders'; import { DashboardCommand } from '../dashboardWebView/DashboardCommand'; @@ -507,7 +507,7 @@ export class Dashboard { * @param files */ private static async updateMediaData(folder: string, files: MediaInfo[]) { - const fileMetadata = await MediaLibrary.getMetadata(folder); + const fileMetadata = await FilesHelper.getMetadata(folder); if (fileMetadata && fileMetadata.length > 0) { files = files.map((m: MediaInfo) => { diff --git a/src/commands/Folders.ts b/src/commands/Folders.ts index 9a586a11..d0d14306 100644 --- a/src/commands/Folders.ts +++ b/src/commands/Folders.ts @@ -6,7 +6,7 @@ import { ContentFolder, FileInfo, FolderInfo } from "../models"; import uniqBy = require("lodash.uniqby"); import { Template } from "./Template"; import { Notifications } from "../helpers/Notifications"; -import { Settings } from "../helpers"; +import { FilesHelper, Settings } from "../helpers"; import { existsSync, mkdirSync } from 'fs'; import { format } from 'date-fns'; import { Dashboard } from './Dashboard'; @@ -205,6 +205,8 @@ export class Folders { for (const folder of folders) { try { + const filesMetadata = await FilesHelper.getMetadata(folder.path); + const projectName = Folders.getProjectFolderName(); let projectStart = folder.path.split(projectName).pop(); if (projectStart) { @@ -219,11 +221,22 @@ export class Folders { for (const file of files) { try { const fileName = basename(file.fsPath); - const stats = await workspace.fs.stat(file); + + let stats: { mtime: number } | null = null; + const foundFile = filesMetadata?.find(f => f.fileName.endsWith(fileName)); + + if (foundFile) { + stats = { + mtime: foundFile.date.getTime() + } + } else { + stats = await workspace.fs.stat(file); + } + fileStats.push({ filePath: file.fsPath, fileName, - ...stats + mtime: stats.mtime }); } catch (error) { // Skip the file diff --git a/src/dashboardWebView/hooks/usePages.tsx b/src/dashboardWebView/hooks/usePages.tsx index 6811f1e6..f963a4a6 100644 --- a/src/dashboardWebView/hooks/usePages.tsx +++ b/src/dashboardWebView/hooks/usePages.tsx @@ -68,7 +68,6 @@ export default function usePages(pages: Page[]) { // Sort the pages let pagesSorted: Page[] = Object.assign([], pagesToShow); - debugger; if (!search) { if (sorting && sorting.id === SortOption.FileNameAsc) { pagesSorted = pagesSorted.sort(Sorting.alphabetically("fmFileName")); diff --git a/src/helpers/FilesHelper.ts b/src/helpers/FilesHelper.ts index 71360ec8..d3cccce0 100644 --- a/src/helpers/FilesHelper.ts +++ b/src/helpers/FilesHelper.ts @@ -1,15 +1,20 @@ -import * as vscode from 'vscode'; +import * as os from 'os'; import { Notifications } from './Notifications'; +import { DateHelper } from './DateHelper'; +import { exec } from 'child_process'; +import { Uri, workspace, env as vscodeEnv } from 'vscode'; +import { parseWinPath } from './parseWinPath'; +import { join } from 'path'; export class FilesHelper { /** * Retrieve all markdown files from the current project */ - public static async getMdFiles(): Promise { - const mdFiles = await vscode.workspace.findFiles('**/*.md', "**/node_modules/**,**/archetypes/**"); - const markdownFiles = await vscode.workspace.findFiles('**/*.markdown', "**/node_modules/**,**/archetypes/**"); - const mdxFiles = await vscode.workspace.findFiles('**/*.mdx', "**/node_modules/**,**/archetypes/**"); + public static async getMdFiles(): Promise { + const mdFiles = await workspace.findFiles('**/*.md', "**/node_modules/**,**/archetypes/**"); + const markdownFiles = await workspace.findFiles('**/*.markdown', "**/node_modules/**,**/archetypes/**"); + const mdxFiles = await workspace.findFiles('**/*.mdx', "**/node_modules/**,**/archetypes/**"); if (!mdFiles && !markdownFiles) { Notifications.info(`No MD files found.`); return null; @@ -18,4 +23,55 @@ export class FilesHelper { const allMdFiles = [...mdFiles, ...markdownFiles, ...mdxFiles]; return allMdFiles; } + + /** + * Retrieve the metadata from all the files in the folder + */ + public static async getMetadata(path: string): Promise<{ date: Date, fileName: string }[] | null> { + return new Promise((resolve) => { + let command: string = ""; + + // Run bash scripts to retrieve metadata faster + if (os.type() === "Darwin") { + command = `cd ${path} +for file in *; do + fdate=$(stat -f "%Sm" -t "%Y-%m-%d %H:%M" "$file") + echo "$file,$fdate" +done`; + } else if (os.type() === "Windows_NT") { + command = `powershell.exe -Command "Get-Item '${parseWinPath(join(path, "/*"))}' | ForEach-Object { Write-Host $_.name','($_.lastwritetime | Get-Date -Format G); }"`; + } else if (os.type() === "Linux" && vscodeEnv.remoteName?.toLowerCase() === "wsl") { + command = `cd ${path} +for file in *; do + fdate=$(stat -c "%y" "$file") + echo "$file,$fdate" +done`; + } else { + resolve(null); + return; + } + + exec(`${command}`, (error, stdout, stderr) => { + if (error) { + resolve(null); + return; + } + + const lines = stdout.replace(/\r/g, '').split('\n').filter(l => l); + const metadata: any[] = []; + + for (let i = 0; i < lines.length; i++) { + const line = lines[i]; + const parts = line.split(','); + + metadata.push({ + fileName: parts[0].replace(/(^"|"$)/g, '').trim(), // Remove quotes at the beginning and end + date: DateHelper.tryParse(parts.slice(1).join(', ').trim(), "MM/d/yyyy h:mm:ss a") + }); + } + + resolve(metadata); + }); + }); + } } \ No newline at end of file diff --git a/src/helpers/MediaLibrary.ts b/src/helpers/MediaLibrary.ts index 6a44e5f4..3e550f82 100644 --- a/src/helpers/MediaLibrary.ts +++ b/src/helpers/MediaLibrary.ts @@ -1,7 +1,6 @@ -import * as os from 'os'; -import { DateHelper } from './DateHelper'; + import { Dashboard } from '../commands/Dashboard'; -import { workspace, env as vscodeEnv } from 'vscode'; +import { workspace } from 'vscode'; import { JsonDB } from 'node-json-db/dist/JsonDB'; import { basename, dirname, join, parse } from 'path'; import { Folders, WORKSPACE_PLACEHOLDER } from '../commands/Folders'; @@ -9,7 +8,6 @@ import { existsSync, renameSync } from 'fs'; import { Notifications } from './Notifications'; import { parseWinPath } from './parseWinPath'; import { LocalStore } from '../constants'; -import { exec } from 'child_process'; interface MediaRecord { description: string; @@ -50,54 +48,6 @@ export class MediaLibrary { return MediaLibrary.instance; } - public static async getMetadata(path: string): Promise<{ date: Date, fileName: string }[] | null> { - return new Promise((resolve) => { - let command: string = ""; - - // Run bash scripts to retrieve metadata faster - if (os.type() === "Darwin") { - command = `for file in *; do - fdate=$(stat -f "%Sm" -t "%Y-%m-%d %H:%M" "$file") - echo "$file,$fdate" -done`; - } else if (os.type() === "Windows_NT") { - resolve(null); - return; - } else if (os.type() === "Linux" && vscodeEnv.remoteName?.toLowerCase() === "wsl") { - command = `for file in *; do - fdate=$(stat -c "%y" "$file") - echo "$file,$fdate" -done`; - } else { - resolve(null); - return; - } - - exec(`cd ${path} && ${command}`, (error, stdout, stderr) => { - if (error) { - resolve(null); - return; - } - - const lines = stdout.split('\n'); - const metadata: any[] = []; - - let lineData: any = {}; - - for (let i = 0; i < lines.length; i++) { - const line = lines[i]; - const parts = line.split(','); - metadata.push({ - fileName: parts[0], - date: DateHelper.tryParse(parts[1]) - }); - } - - resolve(metadata); - }); - }); - } - public get(id: string): MediaRecord | undefined { try { const fileId = this.parsePath(id); diff --git a/src/models/PanelSettings.ts b/src/models/PanelSettings.ts index 1c571046..de7f52a4 100644 --- a/src/models/PanelSettings.ts +++ b/src/models/PanelSettings.ts @@ -1,4 +1,3 @@ -import { FileType } from "vscode"; import { DraftField } from "."; import { Choice } from "./Choice"; import { DashboardData } from "./DashboardData"; @@ -64,10 +63,7 @@ export interface FolderInfo { } export interface FileInfo { - type: FileType; - ctime: number; mtime: number; - size: number; filePath: string; fileName: string; };