mirror of
https://github.com/enso-org/enso.git
synced 2024-11-22 11:52:59 +03:00
Fix opening .enso-project
files
This commit is contained in:
parent
0039c4d6a3
commit
ad89effb5e
@ -34,7 +34,7 @@ const DEFAULT_IMPORT_ONLY_MODULES =
|
||||
'@vitejs\\u002Fplugin-react|node:process|chalk|string-length|yargs|yargs\\u002Fyargs|sharp|to-ico|connect|morgan|serve-static|tiny-invariant|clsx|create-servers|electron-is-dev|fast-glob|esbuild-plugin-.+|opener|tailwindcss.*|enso-assets.*|@modyfi\\u002Fvite-plugin-yaml|is-network-error|validator.+|.*[.]json$'
|
||||
const OUR_MODULES = 'enso-.*'
|
||||
const RELATIVE_MODULES =
|
||||
'bin\\u002Fproject-manager|bin\\u002Fserver|config\\u002Fparser|authentication|config|debug|detect|file-associations|index|ipc|log|naming|paths|preload|project-management|security|url-associations|#\\u002F.*'
|
||||
'bin\\u002Fproject-manager|bin\\u002Fserver|config\\u002Fparser|authentication|config|debug|desktop-environment|detect|file-associations|index|ipc|log|naming|paths|preload|project-management|security|url-associations|#\\u002F.*'
|
||||
const ALLOWED_DEFAULT_IMPORT_MODULES = `${DEFAULT_IMPORT_ONLY_MODULES}|postcss|ajv\\u002Fdist\\u002F2020|${RELATIVE_MODULES}`
|
||||
const STRING_LITERAL = ':matches(Literal[raw=/^["\']/], TemplateLiteral)'
|
||||
const NOT_CAMEL_CASE = '/^(?!_?[a-z][a-z0-9*]*([A-Z0-9][a-z0-9]*)*$)(?!React$)/'
|
||||
|
@ -16,7 +16,7 @@ import * as common from 'enso-common'
|
||||
import GLOBAL_CONFIG from 'enso-common/src/config.json' assert { type: 'json' }
|
||||
import * as contentConfig from 'enso-content-config'
|
||||
import * as ydocServer from 'enso-gui2/ydoc-server'
|
||||
import * as projectManagement from 'enso-project-manager-shim/src/projectManagement'
|
||||
import * as projectManagement from 'project-management'
|
||||
|
||||
import * as paths from '../paths'
|
||||
|
||||
|
81
app/ide-desktop/lib/client/src/desktop-environment.ts
Normal file
81
app/ide-desktop/lib/client/src/desktop-environment.ts
Normal file
@ -0,0 +1,81 @@
|
||||
/**
|
||||
* @file This module contains the logic for the detection of user-specific desktop environment attributes.
|
||||
*/
|
||||
|
||||
import * as childProcess from 'node:child_process'
|
||||
import * as os from 'node:os'
|
||||
import * as path from 'node:path'
|
||||
|
||||
export const DOCUMENTS = getDocumentsPath()
|
||||
|
||||
const CHILD_PROCESS_TIMEOUT = 3000
|
||||
|
||||
/**
|
||||
* Detects path of the user documents directory depending on the operating system.
|
||||
*/
|
||||
function getDocumentsPath(): string | undefined {
|
||||
if (process.platform === 'linux') {
|
||||
return getLinuxDocumentsPath()
|
||||
} else if (process.platform === 'darwin') {
|
||||
return getMacOsDocumentsPath()
|
||||
} else if (process.platform === 'win32') {
|
||||
return getWindowsDocumentsPath()
|
||||
} else {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the user documents path on Linux.
|
||||
*/
|
||||
function getLinuxDocumentsPath(): string {
|
||||
const xdgDocumentsPath = getXdgDocumentsPath()
|
||||
|
||||
return xdgDocumentsPath ?? path.join(os.homedir(), 'enso')
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the documents directory from the XDG directory management system.
|
||||
*/
|
||||
function getXdgDocumentsPath(): string | undefined {
|
||||
const out = childProcess.spawnSync('xdg-user-dir', ['DOCUMENTS'], {
|
||||
timeout: CHILD_PROCESS_TIMEOUT,
|
||||
})
|
||||
|
||||
if (out.error !== undefined) {
|
||||
return
|
||||
} else {
|
||||
return out.stdout.toString().trim()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the user documents path. On macOS, `Documents` acts as a symlink pointing to the
|
||||
* real locale-specific user documents directory.
|
||||
*/
|
||||
function getMacOsDocumentsPath(): string {
|
||||
return path.join(os.homedir(), 'Documents')
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the path to the `My Documents` Windows directory.
|
||||
*/
|
||||
function getWindowsDocumentsPath(): string | undefined {
|
||||
const out = childProcess.spawnSync(
|
||||
'reg',
|
||||
[
|
||||
'query',
|
||||
'HKCU\\Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders',
|
||||
'/v',
|
||||
'personal',
|
||||
],
|
||||
{ timeout: CHILD_PROCESS_TIMEOUT }
|
||||
)
|
||||
|
||||
if (out.error !== undefined) {
|
||||
return
|
||||
} else {
|
||||
const stdoutString = out.stdout.toString()
|
||||
return stdoutString.split(/\s\s+/)[4]
|
||||
}
|
||||
}
|
@ -7,23 +7,28 @@
|
||||
* - if the project is in a different location, we copy it to the Project Manager's location
|
||||
* and open it.
|
||||
* - if the project is a bundle, we extract it to the Project Manager's location and open it. */
|
||||
|
||||
import * as crypto from 'node:crypto'
|
||||
import * as fs from 'node:fs'
|
||||
import * as os from 'node:os'
|
||||
import * as pathModule from 'node:path'
|
||||
import type * as stream from 'node:stream'
|
||||
|
||||
import * as electron from 'electron'
|
||||
import * as tar from 'tar'
|
||||
|
||||
import * as common from 'enso-common'
|
||||
import * as buildUtils from 'enso-common/src/buildUtils'
|
||||
import * as config from 'enso-content-config'
|
||||
import * as desktopEnvironment from 'desktop-environment'
|
||||
|
||||
import * as paths from 'paths'
|
||||
import * as fileAssociations from '../file-associations'
|
||||
const logger = console
|
||||
|
||||
const logger = config.logger
|
||||
// =================
|
||||
// === Constants ===
|
||||
// =================
|
||||
|
||||
export const PACKAGE_METADATA_RELATIVE_PATH = 'package.yaml'
|
||||
export const PROJECT_METADATA_RELATIVE_PATH = '.enso/project.json'
|
||||
/** The filename suffix for the project bundle, including the leading period character. */
|
||||
const BUNDLED_PROJECT_SUFFIX = '.enso-project'
|
||||
|
||||
// ======================
|
||||
// === Project Import ===
|
||||
@ -40,7 +45,7 @@ export function importProjectFromPath(
|
||||
name: string | null = null
|
||||
): string {
|
||||
directory ??= getProjectsDirectory()
|
||||
if (pathModule.extname(openedPath).endsWith(fileAssociations.BUNDLED_PROJECT_SUFFIX)) {
|
||||
if (pathModule.extname(openedPath).endsWith(BUNDLED_PROJECT_SUFFIX)) {
|
||||
logger.log(`Path '${openedPath}' denotes a bundled project.`)
|
||||
// The second part of condition is for the case when someone names a directory
|
||||
// like `my-project.enso-project` and stores the project there.
|
||||
@ -52,7 +57,7 @@ export function importProjectFromPath(
|
||||
return importBundle(openedPath, directory, name)
|
||||
}
|
||||
} else {
|
||||
logger.log(`Opening non-bundled file '${openedPath}'.`)
|
||||
logger.log(`Opening non-bundled file: '${openedPath}'.`)
|
||||
const rootPath = getProjectRoot(openedPath)
|
||||
// Check if the project root is under the projects directory. If it is, we can open it.
|
||||
// Otherwise, we need to install it first.
|
||||
@ -228,7 +233,7 @@ export function getProjectId(projectRoot: string): string | null {
|
||||
|
||||
/** Update the package name. */
|
||||
export function updatePackageName(projectRoot: string, name: string) {
|
||||
const path = pathModule.join(projectRoot, paths.PACKAGE_METADATA_RELATIVE)
|
||||
const path = pathModule.join(projectRoot, PACKAGE_METADATA_RELATIVE_PATH)
|
||||
const contents = fs.readFileSync(path, { encoding: 'utf-8' })
|
||||
const newContents = contents.replace(/^name: .*/, `name: ${name}`)
|
||||
fs.writeFileSync(path, newContents)
|
||||
@ -246,7 +251,7 @@ export function createMetadata(): ProjectMetadata {
|
||||
|
||||
/** Retrieve the project's metadata. */
|
||||
export function getMetadata(projectRoot: string): ProjectMetadata | null {
|
||||
const metadataPath = pathModule.join(projectRoot, paths.PROJECT_METADATA_RELATIVE)
|
||||
const metadataPath = pathModule.join(projectRoot, PROJECT_METADATA_RELATIVE_PATH)
|
||||
try {
|
||||
const jsonText = fs.readFileSync(metadataPath, 'utf8')
|
||||
const metadata: unknown = JSON.parse(jsonText)
|
||||
@ -258,7 +263,7 @@ export function getMetadata(projectRoot: string): ProjectMetadata | null {
|
||||
|
||||
/** Write the project's metadata. */
|
||||
export function writeMetadata(projectRoot: string, metadata: ProjectMetadata): void {
|
||||
const metadataPath = pathModule.join(projectRoot, paths.PROJECT_METADATA_RELATIVE)
|
||||
const metadataPath = pathModule.join(projectRoot, PROJECT_METADATA_RELATIVE_PATH)
|
||||
fs.mkdirSync(pathModule.dirname(metadataPath), { recursive: true })
|
||||
fs.writeFileSync(metadataPath, JSON.stringify(metadata, null, buildUtils.INDENT_SIZE))
|
||||
}
|
||||
@ -284,7 +289,7 @@ export function updateMetadata(
|
||||
/** Check if the given path represents the root of an Enso project.
|
||||
* This is decided by the presence of the Project Manager's metadata. */
|
||||
export function isProjectRoot(candidatePath: string): boolean {
|
||||
const projectJsonPath = pathModule.join(candidatePath, paths.PROJECT_METADATA_RELATIVE)
|
||||
const projectJsonPath = pathModule.join(candidatePath, PROJECT_METADATA_RELATIVE_PATH)
|
||||
try {
|
||||
fs.accessSync(projectJsonPath, fs.constants.R_OK)
|
||||
return true
|
||||
@ -365,7 +370,12 @@ export function getProjectRoot(subtreePath: string): string | null {
|
||||
|
||||
/** Get the directory that stores Enso projects. */
|
||||
export function getProjectsDirectory(): string {
|
||||
return pathModule.join(electron.app.getPath('home'), 'enso', 'projects')
|
||||
const documentsPath = desktopEnvironment.DOCUMENTS
|
||||
if (documentsPath === undefined) {
|
||||
return pathModule.join(os.homedir(), 'enso', 'projects')
|
||||
} else {
|
||||
return pathModule.join(documentsPath, 'enso-projects')
|
||||
}
|
||||
}
|
||||
|
||||
/** Check if the given project is installed, i.e. can be opened with the Project Manager. */
|
||||
@ -387,11 +397,9 @@ export function generateId(): string {
|
||||
return crypto.randomUUID()
|
||||
}
|
||||
|
||||
/** Update the project's ID to a new, unique value, and its last opened date to the current date.
|
||||
* Return the new ID. */
|
||||
/** Update the project's ID to a new, unique value, and its last opened date to the current date. */
|
||||
export function bumpMetadata(projectRoot: string, name: string | null): string {
|
||||
if (name != null) {
|
||||
console.log('nom', name)
|
||||
updatePackageName(projectRoot, name)
|
||||
}
|
||||
return updateMetadata(projectRoot, metadata => ({
|
||||
|
@ -28,7 +28,7 @@ const logger = console
|
||||
export const PACKAGE_METADATA_RELATIVE_PATH = 'package.yaml'
|
||||
export const PROJECT_METADATA_RELATIVE_PATH = '.enso/project.json'
|
||||
/** The filename suffix for the project bundle, including the leading period character. */
|
||||
const BUNDLED_PROJECT_SUFFIX = `.enso-project`
|
||||
const BUNDLED_PROJECT_SUFFIX = '.enso-project'
|
||||
|
||||
// ======================
|
||||
// === Project Import ===
|
||||
|
Loading…
Reference in New Issue
Block a user