Browse Source

CWD detection on windows where possible

Eugene Pankov 4 years ago
parent
commit
aac38fa190

+ 2 - 1
app/package.json

@@ -22,7 +22,7 @@
     "@angular/platform-browser": "^11.1.1",
     "@angular/platform-browser-dynamic": "^11.1.1",
     "@ng-bootstrap/ng-bootstrap": "^6.1.0",
-    "@terminus-term/node-pty": "0.10.0-beta10",
+    "@terminus-term/node-pty": "0.10.0-terminus.2",
     "electron-config": "2.0.0",
     "electron-debug": "^3.2.0",
     "electron-is-dev": "1.2.0",
@@ -32,6 +32,7 @@
     "js-yaml": "4.0.0",
     "keytar": "^7.2.0",
     "mz": "^2.7.0",
+    "native-process-working-directory": "^1.0.2",
     "ngx-toastr": "^12.0.1",
     "npm": "6",
     "path": "0.12.7",

+ 12 - 5
app/yarn.lock

@@ -131,10 +131,10 @@
   dependencies:
     debug "^4.1.1"
 
-"@terminus-term/[email protected]beta10":
-  version "0.10.0-beta10"
-  resolved "https://registry.yarnpkg.com/@terminus-term/node-pty/-/node-pty-0.10.0-beta10.tgz#de9dade3d7549d44b0906ec0d0b9e1bb411f1f21"
-  integrity sha512-j9RJk7sD/es4vR6+AR5M/p3SicVxY6kZEeE0UQKhHNcaAla90/mcGeBNicAWPaAkjO1uQZVbYh5cJMMu5unQgA==
+"@terminus-term/[email protected]terminus.2":
+  version "0.10.0-terminus.2"
+  resolved "https://registry.yarnpkg.com/@terminus-term/node-pty/-/node-pty-0.10.0-terminus.2.tgz#028c7762d13150984bc800b8cd954ceb7dbcac68"
+  integrity sha512-vcscP3jldTMZeHv0XVxQjwEtnh0usUQgUWvsXtPRMy2rMjijwC1+8xFp/FKPpLpWYNTN8WWmRjSdiw+qGGU4CQ==
   dependencies:
     nan "^2.14.0"
 
@@ -2094,6 +2094,13 @@ napi-build-utils@^1.0.1:
   resolved "https://registry.npmjs.org/napi-build-utils/-/napi-build-utils-1.0.2.tgz"
   integrity sha512-ONmRUqK7zj7DWX0D9ADe03wbwOBZxNAfF20PlGfCWQcD3+/MakShIHrMqx9YwPTfxDdF1zLeL+RGZiR9kGMLdg==
 
+native-process-working-directory@^1.0.2:
+  version "1.0.2"
+  resolved "https://registry.yarnpkg.com/native-process-working-directory/-/native-process-working-directory-1.0.2.tgz#7843e2fa1490f53cf8d2c7d1913de8b275e8b89a"
+  integrity sha512-3a67QQV8r3YMUTSOgvtMOCjPDgCpb/8xjv93L8Cqb8bv3hOKsWis4/+8HCu3bgj8ADQV75SCYFSsAGM5G0cXmQ==
+  dependencies:
+    node-addon-api "^3.1.0"
+
 ngx-toastr@^12.0.1:
   version "12.1.0"
   resolved "https://registry.npmjs.org/ngx-toastr/-/ngx-toastr-12.1.0.tgz"
@@ -2113,7 +2120,7 @@ [email protected]:
   resolved "https://registry.npmjs.org/node-addon-api/-/node-addon-api-3.0.0.tgz"
   integrity sha512-sSHCgWfJ+Lui/u+0msF3oyCgvdkhxDbkCS6Q8uiJquzOimkJBvX6hl5aSSA7DR1XbMpdM8r7phjcF63sF4rkKg==
 
-node-addon-api@^3.0.0, node-addon-api@^3.0.2:
+node-addon-api@^3.0.0, node-addon-api@^3.0.2, node-addon-api@^3.1.0:
   version "3.1.0"
   resolved "https://registry.npmjs.org/node-addon-api/-/node-addon-api-3.1.0.tgz"
   integrity sha512-flmrDNB06LIl5lywUz7YlNGZH/5p0M7W28k8hzd9Lshtdh1wshD2Y+U4h9LD6KObOy1f+fEVdgprPrEymjM5uw==

+ 25 - 42
terminus-terminal/src/services/sessions.service.ts

@@ -2,12 +2,11 @@ import * as psNode from 'ps-node'
 import * as fs from 'mz/fs'
 import * as os from 'os'
 import * as nodePTY from '@terminus-term/node-pty'
-
+import { getWorkingDirectoryFromPID } from 'native-process-working-directory'
 import { Observable, Subject } from 'rxjs'
 import { first } from 'rxjs/operators'
 import { Injectable } from '@angular/core'
 import { Logger, LogService, ConfigService, WIN_BUILD_CONPTY_SUPPORTED, isWindowsBuild } from 'terminus-core'
-import { exec } from 'mz/child_process'
 import { SessionOptions } from '../api/interfaces'
 
 /* eslint-disable block-scoped-var */
@@ -20,7 +19,6 @@ try {
     var windowsProcessTree = require('windows-process-tree')  // eslint-disable-line @typescript-eslint/no-var-requires, no-var
 } catch { }
 
-
 export interface ChildProcess {
     pid: number
     ppid: number
@@ -28,7 +26,6 @@ export interface ChildProcess {
 }
 
 const windowsDirectoryRegex = /([a-zA-Z]:[^\:\[\]\?\"\<\>\|]+)/mi
-const catalinaDataVolumePrefix = '/System/Volumes/Data'
 const OSC1337Prefix = Buffer.from('\x1b]1337;')
 const OSC1337Suffix = Buffer.from('\x07')
 
@@ -97,6 +94,7 @@ export class Session extends BaseSession {
     private pauseAfterExit = false
     private guessedCWD: string|null = null
     private reportedCWD: string
+    private initialCWD: string|null = null
 
     constructor (private config: ConfigService) {
         super()
@@ -154,6 +152,7 @@ export class Session extends BaseSession {
                 this.truePID = processes[0].pid
                 processes = await this.getChildProcesses()
             }
+            this.initialCWD = await this.getWorkingDirectory()
         }, 2000)
 
         this.open = true
@@ -261,13 +260,7 @@ export class Session extends BaseSession {
     }
 
     supportsWorkingDirectory (): boolean {
-        if (this.reportedCWD || this.guessedCWD) {
-            return true
-        }
-        if (!this.truePID) {
-            return false
-        }
-        return process.platform !== 'win32'
+        return !!(this.truePID || this.reportedCWD || this.guessedCWD)
     }
 
     async getWorkingDirectory (): Promise<string|null> {
@@ -277,40 +270,30 @@ export class Session extends BaseSession {
         if (!this.truePID) {
             return null
         }
-        if (process.platform === 'darwin') {
-            let lines: string[] = []
-            try {
-                lines = (await exec(`lsof -p ${this.truePID} -Fn`))[0].toString().split('\n')
-            } catch (e) {
-                return null
-            }
-            let cwd = lines[lines[1] === 'fcwd' ? 2 : 1].substring(1)
-            if (cwd.startsWith(catalinaDataVolumePrefix)) {
-                cwd = cwd.substring(catalinaDataVolumePrefix.length)
-            }
-            return cwd
+        let cwd: string|null = null
+        try {
+            cwd = getWorkingDirectoryFromPID(this.truePID)
+        } catch (exc) {
+            console.error(exc)
         }
-        if (process.platform === 'linux') {
-            try {
-                const cwd = await fs.readlink(`/proc/${this.truePID}/cwd`)
-                return cwd
-            } catch (exc) {
-                console.error(exc)
-                return null
-            }
+
+        try {
+            cwd = await fs.realpath(cwd)
+        } catch {}
+
+        if (process.platform === 'win32' && (cwd === this.initialCWD || cwd === process.env.WINDIR)) {
+            // shell doesn't truly change its process' CWD
+            cwd = null
         }
-        if (process.platform === 'win32') {
-            if (!this.guessedCWD) {
-                return null
-            }
-            try {
-                await fs.access(this.guessedCWD)
-            } catch (e) {
-                return null
-            }
-            return this.guessedCWD
+
+        cwd = cwd || this.guessedCWD
+
+        try {
+            await fs.access(cwd)
+        } catch {
+            return null
         }
-        return null
+        return cwd
     }
 
     private guessWindowsCWD (data: string) {

+ 1 - 0
terminus-terminal/webpack.config.js

@@ -67,6 +67,7 @@ module.exports = {
         'windows-native-registry',
         '@terminus-term/node-pty',
         'windows-process-tree',
+        'native-process-working-directory',
         'os',
         /^rxjs/,
         /^@angular/,