pinokiod 3.107.0 → 3.109.0
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/kernel/bin/caddy.js +24 -0
- package/kernel/bin/git.js +12 -0
- package/kernel/environment.js +76 -0
- package/kernel/git.js +21 -23
- package/kernel/scripts/git/fork +21 -0
- package/kernel/scripts/git/push +1 -1
- package/package.json +1 -1
- package/server/index.js +123 -94
- package/server/public/layout.js +21 -0
- package/server/views/app.ejs +1159 -123
- package/server/views/file_explorer.ejs +1 -1
- package/server/views/index.ejs +1 -1
- package/server/views/index2.ejs +1 -1
- package/server/views/partials/dynamic.ejs +1 -1
- package/server/views/partials/menu.ejs +1 -1
- package/server/views/pro.ejs +1 -1
package/kernel/bin/caddy.js
CHANGED
|
@@ -23,6 +23,26 @@ class Caddy {
|
|
|
23
23
|
}
|
|
24
24
|
}
|
|
25
25
|
async start() {
|
|
26
|
+
// if peer.https_active is true,
|
|
27
|
+
// 1. kill existing caddy
|
|
28
|
+
// 2. start caddy
|
|
29
|
+
if (!this.kernel.peer || !("https_active" in this.kernel.peer)) {
|
|
30
|
+
// wait until they are available
|
|
31
|
+
await new Promise((resolve, reject) => {
|
|
32
|
+
let interval = setInterval(() => {
|
|
33
|
+
console.log("wait until peer becomes available")
|
|
34
|
+
if (this.kernel.peer && "https_active" in this.kernel.peer) {
|
|
35
|
+
console.log("peer ready")
|
|
36
|
+
clearInterval(interval)
|
|
37
|
+
resolve()
|
|
38
|
+
}
|
|
39
|
+
}, 1000)
|
|
40
|
+
})
|
|
41
|
+
}
|
|
42
|
+
if (!this.kernel.peer.https_active) {
|
|
43
|
+
console.log("https_active false")
|
|
44
|
+
return
|
|
45
|
+
}
|
|
26
46
|
// console.log("Existing caddy pid?", this.kernel.processes.caddy_pid)
|
|
27
47
|
let running = await this.running()
|
|
28
48
|
console.log("Caddy running?", running)
|
|
@@ -31,6 +51,7 @@ class Caddy {
|
|
|
31
51
|
console.log("kill existing caddy before restarting")
|
|
32
52
|
await new Promise((resolve, reject) => {
|
|
33
53
|
let interval = setInterval(() => {
|
|
54
|
+
console.log("CADDY_PID", this.kernel.processes.caddy_pid)
|
|
34
55
|
if (this.kernel.processes.caddy_pid) {
|
|
35
56
|
try {
|
|
36
57
|
console.log("kill caddy", this.kernel.processes.caddy_pid)
|
|
@@ -39,10 +60,12 @@ class Caddy {
|
|
|
39
60
|
clearInterval(interval)
|
|
40
61
|
resolve()
|
|
41
62
|
} catch (error) {
|
|
63
|
+
console.log("ERROR", error)
|
|
42
64
|
clearInterval(interval)
|
|
43
65
|
reject(error)
|
|
44
66
|
}
|
|
45
67
|
} else {
|
|
68
|
+
//clearInterval(interval)
|
|
46
69
|
console.log("try killing existing caddy again in 1 sec")
|
|
47
70
|
}
|
|
48
71
|
}, 1000)
|
|
@@ -76,6 +99,7 @@ class Caddy {
|
|
|
76
99
|
this.kernel.peer.announce()
|
|
77
100
|
console.log("announced to peers")
|
|
78
101
|
// this.kernel.refresh(true)
|
|
102
|
+
} else {
|
|
79
103
|
}
|
|
80
104
|
}
|
|
81
105
|
async install(req, ondata, kernel, id) {
|
package/kernel/bin/git.js
CHANGED
|
@@ -49,6 +49,13 @@ class Git {
|
|
|
49
49
|
}
|
|
50
50
|
|
|
51
51
|
await fs.promises.mkdir(this.kernel.path("scripts/git"), { recursive: true }).catch((e) => { })
|
|
52
|
+
|
|
53
|
+
let gitfork_path = path.resolve(this.kernel.homedir, "scripts/git/fork.json")
|
|
54
|
+
await fs.promises.copyFile(
|
|
55
|
+
path.resolve(__dirname, "..", "scripts/git/fork"),
|
|
56
|
+
gitfork_path
|
|
57
|
+
)
|
|
58
|
+
|
|
52
59
|
let gitpush_path = path.resolve(this.kernel.homedir, "scripts/git/push.json")
|
|
53
60
|
await fs.promises.copyFile(
|
|
54
61
|
path.resolve(__dirname, "..", "scripts/git/push"),
|
|
@@ -106,6 +113,11 @@ class Git {
|
|
|
106
113
|
if (!exists4) {
|
|
107
114
|
return false;
|
|
108
115
|
}
|
|
116
|
+
let gitfork_path = path.resolve(this.kernel.homedir, "scripts/git/fork.json")
|
|
117
|
+
let exists5 = await this.kernel.api.exists(gitfork_path)
|
|
118
|
+
if (!exists5) {
|
|
119
|
+
return false;
|
|
120
|
+
}
|
|
109
121
|
|
|
110
122
|
if (this.kernel.platform === "darwin") {
|
|
111
123
|
let gh_config_exists = await this.kernel.exists("config/gh")
|
package/kernel/environment.js
CHANGED
|
@@ -557,6 +557,82 @@ const init = async (options, kernel) => {
|
|
|
557
557
|
}
|
|
558
558
|
}
|
|
559
559
|
}
|
|
560
|
+
|
|
561
|
+
const agentTemplatePath = kernel.path("prototype/system/AGENTS.md")
|
|
562
|
+
const agentTemplateExists = await kernel.exists(agentTemplatePath)
|
|
563
|
+
if (agentTemplateExists) {
|
|
564
|
+
const agentFiles = [
|
|
565
|
+
"AGENTS.md",
|
|
566
|
+
"CLAUDE.md",
|
|
567
|
+
"GEMINI.md",
|
|
568
|
+
"QWEN.md",
|
|
569
|
+
".windsurfrules",
|
|
570
|
+
".cursorrules",
|
|
571
|
+
".clinerules"
|
|
572
|
+
]
|
|
573
|
+
const structure_path = kernel.path("prototype/system/structure/clone")
|
|
574
|
+
const structure_content = await fs.promises.readFile(structure_path, "utf-8")
|
|
575
|
+
const rendered_recipe = await kernel.renderFile(agentTemplatePath, {
|
|
576
|
+
structure: structure_content,
|
|
577
|
+
examples: kernel.path("prototype/system/examples"),
|
|
578
|
+
browser_logs: kernel.path("logs/browser.log"),
|
|
579
|
+
PINOKIO_DOCUMENTATION: kernel.path("prototype/PINOKIO.md"),
|
|
580
|
+
PTERM_DOCUMENTATION: kernel.path("prototype/PTERM.md"),
|
|
581
|
+
app_root: root
|
|
582
|
+
})
|
|
583
|
+
for (const filename of agentFiles) {
|
|
584
|
+
const destination = path.resolve(root, filename)
|
|
585
|
+
const destinationExists = await kernel.exists(destination)
|
|
586
|
+
if (!destinationExists) {
|
|
587
|
+
await fs.promises.writeFile(destination, rendered_recipe)
|
|
588
|
+
}
|
|
589
|
+
}
|
|
590
|
+
}
|
|
591
|
+
|
|
592
|
+
const gitDir = path.resolve(root, ".git")
|
|
593
|
+
const gitDirExists = await kernel.exists(gitDir)
|
|
594
|
+
if (gitDirExists) {
|
|
595
|
+
const excludePath = path.resolve(gitDir, "info/exclude")
|
|
596
|
+
await fs.promises.mkdir(path.dirname(excludePath), { recursive: true })
|
|
597
|
+
|
|
598
|
+
let excludeContent = ""
|
|
599
|
+
try {
|
|
600
|
+
excludeContent = await fs.promises.readFile(excludePath, "utf8")
|
|
601
|
+
} catch (error) {
|
|
602
|
+
if (error.code !== "ENOENT") {
|
|
603
|
+
throw error
|
|
604
|
+
}
|
|
605
|
+
}
|
|
606
|
+
|
|
607
|
+
const existingEntries = new Set(
|
|
608
|
+
excludeContent
|
|
609
|
+
.split(/\r?\n/)
|
|
610
|
+
.map(line => line.trim())
|
|
611
|
+
.filter(line => line.length > 0)
|
|
612
|
+
)
|
|
613
|
+
|
|
614
|
+
const entriesToEnsure = [
|
|
615
|
+
"ENVIRONMENT",
|
|
616
|
+
".*",
|
|
617
|
+
"~*",
|
|
618
|
+
"/logs/",
|
|
619
|
+
"/cache/",
|
|
620
|
+
"/AGENTS.md",
|
|
621
|
+
"/CLAUDE.md",
|
|
622
|
+
"/GEMINI.md",
|
|
623
|
+
"/QWEN.md"
|
|
624
|
+
]
|
|
625
|
+
|
|
626
|
+
const missingEntries = entriesToEnsure.filter(entry => !existingEntries.has(entry))
|
|
627
|
+
if (missingEntries.length > 0) {
|
|
628
|
+
let appendContent = ""
|
|
629
|
+
if (excludeContent.length > 0 && !excludeContent.endsWith("\n")) {
|
|
630
|
+
appendContent += "\n"
|
|
631
|
+
}
|
|
632
|
+
appendContent += missingEntries.join("\n") + "\n"
|
|
633
|
+
await fs.promises.appendFile(excludePath, appendContent)
|
|
634
|
+
}
|
|
635
|
+
}
|
|
560
636
|
return {
|
|
561
637
|
relpath,
|
|
562
638
|
root_path: root,
|
package/kernel/git.js
CHANGED
|
@@ -67,41 +67,39 @@ class Git {
|
|
|
67
67
|
display_name = `${name}/${gitRelPathSansGit}`
|
|
68
68
|
main = false
|
|
69
69
|
}
|
|
70
|
+
let gitRemote = null
|
|
70
71
|
try {
|
|
71
|
-
|
|
72
|
+
gitRemote = await git.getConfig({
|
|
72
73
|
fs,
|
|
73
74
|
http,
|
|
74
75
|
dir,
|
|
75
76
|
path: 'remote.origin.url'
|
|
76
77
|
})
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
78
|
+
} catch (_) {}
|
|
79
|
+
|
|
80
|
+
const repoEntry = {
|
|
81
|
+
main,
|
|
82
|
+
name: display_name,
|
|
83
|
+
gitPath,
|
|
84
|
+
gitRelPath,
|
|
85
|
+
gitParentPath,
|
|
86
|
+
gitParentRelPath,
|
|
87
|
+
dir,
|
|
88
|
+
}
|
|
89
|
+
if (gitRemote) {
|
|
90
|
+
repoEntry.url = gitRemote
|
|
91
|
+
}
|
|
92
|
+
repos.push(repoEntry)
|
|
93
|
+
|
|
94
|
+
if (gitRemote && !this.mapping[gitRemote]) {
|
|
95
|
+
try {
|
|
88
96
|
let head = await this.getHead(gitParentPath)
|
|
89
97
|
this.mapping[gitRemote] = {
|
|
90
98
|
main,
|
|
91
99
|
path: gitParentPath,
|
|
92
100
|
head
|
|
93
101
|
}
|
|
94
|
-
}
|
|
95
|
-
} catch (e) {
|
|
96
|
-
repos.push({
|
|
97
|
-
main,
|
|
98
|
-
name: display_name,
|
|
99
|
-
gitPath,
|
|
100
|
-
gitRelPath,
|
|
101
|
-
gitParentPath,
|
|
102
|
-
gitParentRelPath,
|
|
103
|
-
dir,
|
|
104
|
-
})
|
|
102
|
+
} catch (_) {}
|
|
105
103
|
}
|
|
106
104
|
this.dirs.add(dir)
|
|
107
105
|
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
{
|
|
2
|
+
"run": [{
|
|
3
|
+
"when": "{{args.org}}",
|
|
4
|
+
"method": "shell.run",
|
|
5
|
+
"params": {
|
|
6
|
+
"path": "{{args.cwd}}",
|
|
7
|
+
"message": [
|
|
8
|
+
"gh repo fork --remote=true --clone=false --fork-name {{args.name}} --org {{args.org}}"
|
|
9
|
+
]
|
|
10
|
+
}
|
|
11
|
+
}, {
|
|
12
|
+
"when": "{{!args.org}}",
|
|
13
|
+
"method": "shell.run",
|
|
14
|
+
"params": {
|
|
15
|
+
"path": "{{args.cwd}}",
|
|
16
|
+
"message": [
|
|
17
|
+
"gh repo fork --remote=true --clone=false --fork-name {{args.name}}"
|
|
18
|
+
]
|
|
19
|
+
}
|
|
20
|
+
}]
|
|
21
|
+
}
|
package/kernel/scripts/git/push
CHANGED
package/package.json
CHANGED
package/server/index.js
CHANGED
|
@@ -484,98 +484,112 @@ class Server {
|
|
|
484
484
|
}
|
|
485
485
|
}
|
|
486
486
|
async getGit(ref, filepath) {
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
if (branches.length === 0) {
|
|
491
|
-
return {}
|
|
492
|
-
// const defaultBranch = 'main';
|
|
493
|
-
// await git.init({ fs, dir, defaultBranch });
|
|
494
|
-
// branches = await git.listBranches({ fs, dir });
|
|
495
|
-
// const current = await git.currentBranch({ fs, dir, fullname: false }) || defaultBranch;
|
|
496
|
-
// if (!branches.includes(current)) {
|
|
497
|
-
// branches.unshift(current);
|
|
498
|
-
// }
|
|
499
|
-
// if (!ref || ref === 'HEAD') {
|
|
500
|
-
// ref = current;
|
|
501
|
-
// }
|
|
502
|
-
}
|
|
503
|
-
let log = []
|
|
487
|
+
const dir = this.kernel.path("api", filepath)
|
|
488
|
+
|
|
489
|
+
let branchList = []
|
|
504
490
|
try {
|
|
505
|
-
|
|
506
|
-
|
|
491
|
+
branchList = await git.listBranches({ fs, dir })
|
|
492
|
+
} catch (_) {}
|
|
493
|
+
|
|
494
|
+
const collectLog = async (targetRef) => {
|
|
495
|
+
const entries = await git.log({ fs, dir, depth: 50, ref: targetRef })
|
|
496
|
+
entries.forEach((item) => {
|
|
507
497
|
item.info = `/gitcommit/${item.oid}/${filepath}`
|
|
508
498
|
})
|
|
509
|
-
|
|
510
|
-
|
|
499
|
+
return entries
|
|
500
|
+
}
|
|
501
|
+
|
|
502
|
+
let log = []
|
|
503
|
+
let logError = null
|
|
504
|
+
if (ref) {
|
|
505
|
+
try {
|
|
506
|
+
log = await collectLog(ref)
|
|
507
|
+
} catch (error) {
|
|
508
|
+
logError = error
|
|
509
|
+
}
|
|
510
|
+
}
|
|
511
|
+
if (log.length === 0) {
|
|
512
|
+
try {
|
|
513
|
+
log = await collectLog('HEAD')
|
|
514
|
+
} catch (error) {
|
|
515
|
+
if (!logError) {
|
|
516
|
+
logError = error
|
|
517
|
+
}
|
|
518
|
+
}
|
|
519
|
+
}
|
|
520
|
+
|
|
521
|
+
let currentBranch = null
|
|
522
|
+
try {
|
|
523
|
+
currentBranch = await git.currentBranch({ fs, dir, fullname: false })
|
|
524
|
+
} catch (_) {}
|
|
525
|
+
|
|
526
|
+
let branches = []
|
|
527
|
+
if (branchList.length > 0) {
|
|
528
|
+
branches = branchList.map((name) => ({
|
|
529
|
+
branch: name,
|
|
530
|
+
selected: currentBranch ? name === currentBranch : false
|
|
531
|
+
}))
|
|
532
|
+
if (!currentBranch && log.length > 0) {
|
|
533
|
+
const headOid = log[0].oid
|
|
534
|
+
branches = [{ branch: headOid, selected: true }, ...branches.map((entry) => ({ ...entry, selected: false }))]
|
|
535
|
+
currentBranch = headOid
|
|
536
|
+
}
|
|
537
|
+
} else {
|
|
538
|
+
if (currentBranch) {
|
|
539
|
+
branches = [{ branch: currentBranch, selected: true }]
|
|
540
|
+
} else if (log.length > 0) {
|
|
541
|
+
const headOid = log[0].oid
|
|
542
|
+
branches = [{ branch: headOid, selected: true }]
|
|
543
|
+
currentBranch = headOid
|
|
544
|
+
}
|
|
545
|
+
}
|
|
546
|
+
|
|
547
|
+
if (!currentBranch && log.length > 0) {
|
|
548
|
+
currentBranch = log[0].oid
|
|
511
549
|
}
|
|
512
550
|
|
|
513
|
-
|
|
551
|
+
if (branches.length === 0) {
|
|
552
|
+
branches = [{ branch: currentBranch || 'HEAD', selected: true }]
|
|
553
|
+
}
|
|
554
|
+
|
|
555
|
+
const config = await this.kernel.git.config(dir)
|
|
514
556
|
|
|
515
557
|
let hosts = ""
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
hosts = await fs.promises.readFile(hosts_file, "utf8")
|
|
558
|
+
const hostsFile = this.kernel.path("config/gh/hosts.yml")
|
|
559
|
+
if (await this.exists(hostsFile)) {
|
|
560
|
+
hosts = await fs.promises.readFile(hostsFile, "utf8")
|
|
520
561
|
if (hosts.startsWith("{}")) {
|
|
521
562
|
hosts = ""
|
|
522
563
|
}
|
|
523
564
|
}
|
|
524
|
-
|
|
565
|
+
const connected = hosts.length > 0
|
|
566
|
+
|
|
525
567
|
let remote = null
|
|
526
|
-
if (config["remote \"origin\""]) {
|
|
568
|
+
if (config && config["remote \"origin\""]) {
|
|
527
569
|
remote = config["remote \"origin\""].url
|
|
528
570
|
}
|
|
529
571
|
|
|
530
|
-
// Get all remotes
|
|
531
572
|
let remotes = []
|
|
532
573
|
try {
|
|
533
574
|
remotes = await git.listRemotes({ fs, dir, verbose: true })
|
|
534
|
-
} catch (
|
|
535
|
-
console.log("Remotes error", e)
|
|
536
|
-
}
|
|
575
|
+
} catch (_) {}
|
|
537
576
|
|
|
538
|
-
|
|
577
|
+
if (!currentBranch) {
|
|
578
|
+
currentBranch = 'HEAD'
|
|
579
|
+
}
|
|
539
580
|
|
|
540
|
-
|
|
541
|
-
|
|
581
|
+
return {
|
|
582
|
+
ref,
|
|
583
|
+
config,
|
|
584
|
+
remote,
|
|
585
|
+
remotes,
|
|
586
|
+
connected,
|
|
587
|
+
log,
|
|
588
|
+
branch: currentBranch,
|
|
589
|
+
branches,
|
|
542
590
|
dir,
|
|
543
|
-
|
|
544
|
-
});
|
|
545
|
-
|
|
546
|
-
// if current branch exitss => currengt branch is selected
|
|
547
|
-
// if current branch does not exist => get logs[0].oid
|
|
548
|
-
if (branch) {
|
|
549
|
-
branches = branches.map((b) => {
|
|
550
|
-
if (b === branch) {
|
|
551
|
-
return {
|
|
552
|
-
branch: b,
|
|
553
|
-
selected: true
|
|
554
|
-
}
|
|
555
|
-
} else {
|
|
556
|
-
return {
|
|
557
|
-
branch: b,
|
|
558
|
-
selected: false
|
|
559
|
-
}
|
|
560
|
-
}
|
|
561
|
-
})
|
|
562
|
-
} else {
|
|
563
|
-
branches.push(log[0].oid)
|
|
564
|
-
branches = branches.map((b) => {
|
|
565
|
-
if (b === log[0].oid) {
|
|
566
|
-
return {
|
|
567
|
-
branch: b,
|
|
568
|
-
selected: true
|
|
569
|
-
}
|
|
570
|
-
} else {
|
|
571
|
-
return {
|
|
572
|
-
branch: b,
|
|
573
|
-
selected: false
|
|
574
|
-
}
|
|
575
|
-
}
|
|
576
|
-
})
|
|
591
|
+
logError: logError ? String(logError.message || logError) : null
|
|
577
592
|
}
|
|
578
|
-
return { ref, config, remote, remotes, connected, log, branch, branches, dir }
|
|
579
593
|
}
|
|
580
594
|
async init_env(env_dir_path, options) {
|
|
581
595
|
let current = this.kernel.path(env_dir_path, "ENVIRONMENT")
|
|
@@ -696,25 +710,28 @@ class Server {
|
|
|
696
710
|
|
|
697
711
|
await Environment.init({ name }, this.kernel)
|
|
698
712
|
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
let
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
713
|
+
/*
|
|
714
|
+
REPLACED OUT WITH using .git/info/exclude instead in order to not mess with 3rd party project .gitignore files but still exclude
|
|
715
|
+
*/
|
|
716
|
+
// // copy gitignore from ~pinokio/prototype/system/gitignore if it doesn't exist
|
|
717
|
+
//
|
|
718
|
+
//
|
|
719
|
+
// let gitignore_path = this.kernel.path("api/" + name + "/.gitignore")
|
|
720
|
+
// let dot_path = this.kernel.path("api", name, "pinokio")
|
|
721
|
+
// let gitignore_template_path = this.kernel.path("prototype/system/gitignore")
|
|
722
|
+
// let template_exists = await this.exists(gitignore_template_path)
|
|
723
|
+
// if (template_exists) {
|
|
724
|
+
// let exists = await this.exists(dot_path)
|
|
725
|
+
// if (exists) {
|
|
726
|
+
// // 1. when importing existing projects (.pinokio exists), don't mess with .gitignore
|
|
727
|
+
// } else {
|
|
728
|
+
// // 2. otherwise, merge gitignore
|
|
729
|
+
// await Util.mergeLines(
|
|
730
|
+
// gitignore_path, // existing path
|
|
731
|
+
// gitignore_template_path // overwrite with template
|
|
732
|
+
// )
|
|
733
|
+
// }
|
|
734
|
+
// }
|
|
718
735
|
|
|
719
736
|
|
|
720
737
|
|
|
@@ -848,7 +865,8 @@ class Server {
|
|
|
848
865
|
git_history_url: `/info/git/HEAD/${name}`,
|
|
849
866
|
git_status_url: `/info/gitstatus/${name}`,
|
|
850
867
|
git_push_url: `/run/scripts/git/push.json?cwd=${encodeURIComponent(this.kernel.path('api', name))}`,
|
|
851
|
-
git_create_url: `/run/scripts/git/create.json?cwd=${encodeURIComponent(this.kernel.path('api', name))}
|
|
868
|
+
git_create_url: `/run/scripts/git/create.json?cwd=${encodeURIComponent(this.kernel.path('api', name))}`,
|
|
869
|
+
git_fork_url: `/run/scripts/git/fork.json?cwd=${encodeURIComponent(this.kernel.path('api', name))}`
|
|
852
870
|
// rawpath,
|
|
853
871
|
}
|
|
854
872
|
// if (!this.kernel.proto.config) {
|
|
@@ -1202,10 +1220,15 @@ class Server {
|
|
|
1202
1220
|
|
|
1203
1221
|
const repoHistoryUrl = repoParam ? `/info/git/HEAD/${repoParam}` : null
|
|
1204
1222
|
|
|
1223
|
+
const forkUrl = `/run/scripts/git/fork.json?cwd=${encodeURIComponent(dir)}`
|
|
1224
|
+
const pushUrl = `/run/scripts/git/push.json?cwd=${encodeURIComponent(dir)}`
|
|
1225
|
+
|
|
1205
1226
|
return {
|
|
1206
1227
|
changes,
|
|
1207
1228
|
git_commit_url: `/run/scripts/git/commit.json?cwd=${dir}&callback_target=parent&callback=$location.href`,
|
|
1208
1229
|
git_history_url: repoHistoryUrl,
|
|
1230
|
+
git_fork_url: forkUrl,
|
|
1231
|
+
git_push_url: pushUrl,
|
|
1209
1232
|
}
|
|
1210
1233
|
}
|
|
1211
1234
|
async computeWorkspaceGitStatus(workspaceName) {
|
|
@@ -1218,7 +1241,7 @@ class Server {
|
|
|
1218
1241
|
for (const repo of repos) {
|
|
1219
1242
|
const repoParam = repo.gitParentRelPath || workspaceName
|
|
1220
1243
|
try {
|
|
1221
|
-
const { changes, git_commit_url, git_history_url } = await this.getRepoHeadStatus(repoParam)
|
|
1244
|
+
const { changes, git_commit_url, git_history_url, git_fork_url, git_push_url } = await this.getRepoHeadStatus(repoParam)
|
|
1222
1245
|
const historyUrl = git_history_url || (repoParam ? `/info/git/HEAD/${repoParam}` : `/info/git/HEAD/${workspaceName}`)
|
|
1223
1246
|
statuses.push({
|
|
1224
1247
|
name: repo.name,
|
|
@@ -1229,6 +1252,8 @@ class Server {
|
|
|
1229
1252
|
changes,
|
|
1230
1253
|
git_commit_url,
|
|
1231
1254
|
git_history_url: historyUrl,
|
|
1255
|
+
git_fork_url,
|
|
1256
|
+
git_push_url,
|
|
1232
1257
|
url: repo.url || null,
|
|
1233
1258
|
})
|
|
1234
1259
|
} catch (error) {
|
|
@@ -1243,6 +1268,8 @@ class Server {
|
|
|
1243
1268
|
changes: [],
|
|
1244
1269
|
git_commit_url: null,
|
|
1245
1270
|
git_history_url: historyUrl,
|
|
1271
|
+
git_fork_url: `/run/scripts/git/fork.json?cwd=${encodeURIComponent(this.kernel.path('api', repoParam))}`,
|
|
1272
|
+
git_push_url: `/run/scripts/git/push.json?cwd=${encodeURIComponent(this.kernel.path('api', repoParam))}`,
|
|
1246
1273
|
url: repo.url || null,
|
|
1247
1274
|
error: error ? String(error.message || error) : 'unknown',
|
|
1248
1275
|
})
|
|
@@ -4071,11 +4098,14 @@ class Server {
|
|
|
4071
4098
|
defaultUrl.searchParams.set('mode', 'settings')
|
|
4072
4099
|
}
|
|
4073
4100
|
|
|
4101
|
+
const initialPath = initialUrl.pathname + initialUrl.search + initialUrl.hash
|
|
4102
|
+
const defaultPath = defaultUrl.pathname + defaultUrl.search + defaultUrl.hash
|
|
4103
|
+
|
|
4074
4104
|
res.render('layout', {
|
|
4075
4105
|
theme: this.theme,
|
|
4076
4106
|
agent: req.agent,
|
|
4077
|
-
initialPath
|
|
4078
|
-
defaultPath
|
|
4107
|
+
initialPath,
|
|
4108
|
+
defaultPath,
|
|
4079
4109
|
sessionId: typeof req.query.session === 'string' ? req.query.session : null
|
|
4080
4110
|
})
|
|
4081
4111
|
}))
|
|
@@ -5519,7 +5549,6 @@ class Server {
|
|
|
5519
5549
|
// }))
|
|
5520
5550
|
this.app.post("/env", ex(async (req, res) => {
|
|
5521
5551
|
let fullpath = path.resolve(this.kernel.homedir, req.body.filepath, "ENVIRONMENT")
|
|
5522
|
-
console.log({ fullpath })
|
|
5523
5552
|
let updated = req.body.vals
|
|
5524
5553
|
let hosts = req.body.hosts
|
|
5525
5554
|
await Util.update_env(fullpath, updated)
|
package/server/public/layout.js
CHANGED
|
@@ -37,6 +37,26 @@
|
|
|
37
37
|
const leafElements = new Map();
|
|
38
38
|
const gutterElements = new Map();
|
|
39
39
|
const layoutCache = new Map();
|
|
40
|
+
const PRESERVED_QUERY_PARAMS = new Set(['session']);
|
|
41
|
+
|
|
42
|
+
function stripTransientQueryParams() {
|
|
43
|
+
try {
|
|
44
|
+
const url = new URL(window.location.href);
|
|
45
|
+
let changed = false;
|
|
46
|
+
const keys = Array.from(url.searchParams.keys());
|
|
47
|
+
keys.forEach((key) => {
|
|
48
|
+
if (!PRESERVED_QUERY_PARAMS.has(key)) {
|
|
49
|
+
url.searchParams.delete(key);
|
|
50
|
+
changed = true;
|
|
51
|
+
}
|
|
52
|
+
});
|
|
53
|
+
if (changed) {
|
|
54
|
+
window.history.replaceState(window.history.state, '', url.toString());
|
|
55
|
+
}
|
|
56
|
+
} catch (_) {
|
|
57
|
+
// ignore malformed URLs
|
|
58
|
+
}
|
|
59
|
+
}
|
|
40
60
|
|
|
41
61
|
function normalizeSrc(raw) {
|
|
42
62
|
if (!raw || typeof raw !== 'string') {
|
|
@@ -698,6 +718,7 @@
|
|
|
698
718
|
applyLayout();
|
|
699
719
|
attachGutterHandlers();
|
|
700
720
|
broadcastLayoutState();
|
|
721
|
+
stripTransientQueryParams();
|
|
701
722
|
}
|
|
702
723
|
|
|
703
724
|
function onResize() {
|