pinokiod 3.102.0 → 3.103.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/package.json +1 -1
- package/server/index.js +396 -31
- package/server/views/app.ejs +722 -91
package/package.json
CHANGED
package/server/index.js
CHANGED
|
@@ -83,6 +83,23 @@ class Server {
|
|
|
83
83
|
this.kernel.version = this.version
|
|
84
84
|
this.upload = multer();
|
|
85
85
|
this.cf = new Cloudflare()
|
|
86
|
+
this.virtualEnvCache = new Map()
|
|
87
|
+
this.gitStatusIgnorePatterns = [
|
|
88
|
+
/^node_modules\//,
|
|
89
|
+
/^vendor\//,
|
|
90
|
+
/^\.venv\//,
|
|
91
|
+
/^venv\//,
|
|
92
|
+
/^\.virtualenv\//,
|
|
93
|
+
/^env\//,
|
|
94
|
+
/^__pycache__\//,
|
|
95
|
+
/^build\//,
|
|
96
|
+
/^dist\//,
|
|
97
|
+
/^tmp\//,
|
|
98
|
+
/^\.cache\//,
|
|
99
|
+
/^\.mypy_cache\//,
|
|
100
|
+
/^\.pytest_cache\//,
|
|
101
|
+
/^\.git\//
|
|
102
|
+
]
|
|
86
103
|
|
|
87
104
|
// sometimes the C:\Windows\System32 is not in PATH, need to add
|
|
88
105
|
let platform = os.platform()
|
|
@@ -829,6 +846,7 @@ class Server {
|
|
|
829
846
|
execUrl: "/api/" + name,
|
|
830
847
|
git_monitor_url: `/gitcommit/HEAD/${name}`,
|
|
831
848
|
git_history_url: `/info/git/HEAD/${name}`,
|
|
849
|
+
git_status_url: `/info/gitstatus/${name}`,
|
|
832
850
|
git_push_url: `/run/scripts/git/push.json?cwd=${encodeURIComponent(this.kernel.path('api', name))}`,
|
|
833
851
|
git_create_url: `/run/scripts/git/create.json?cwd=${encodeURIComponent(this.kernel.path('api', name))}`
|
|
834
852
|
// rawpath,
|
|
@@ -869,6 +887,371 @@ class Server {
|
|
|
869
887
|
let check = !!relative && !relative.startsWith('..') && !path.isAbsolute(relative);
|
|
870
888
|
return check
|
|
871
889
|
}
|
|
890
|
+
async discoverVirtualEnvDirs(dir) {
|
|
891
|
+
const cacheKey = path.resolve(dir)
|
|
892
|
+
const cached = this.virtualEnvCache.get(cacheKey)
|
|
893
|
+
const now = Date.now()
|
|
894
|
+
if (cached && cached.timestamp && (now - cached.timestamp) < 60000) {
|
|
895
|
+
return cached.dirs
|
|
896
|
+
}
|
|
897
|
+
|
|
898
|
+
const normalizePath = (p) => p.replace(/\\/g, '/').replace(/\/+/g, '/')
|
|
899
|
+
const ignored = new Set()
|
|
900
|
+
const autoExclude = new Set()
|
|
901
|
+
const seen = new Set()
|
|
902
|
+
const stack = [{ abs: dir, rel: '', depth: 0 }]
|
|
903
|
+
const maxDepth = 6
|
|
904
|
+
|
|
905
|
+
const shouldIgnoreRelative = (relative) => {
|
|
906
|
+
if (!relative) {
|
|
907
|
+
return false
|
|
908
|
+
}
|
|
909
|
+
const normalized = normalizePath(relative)
|
|
910
|
+
return this.gitStatusIgnorePatterns.some((regex) => regex.test(normalized) || regex.test(`${normalized}/`))
|
|
911
|
+
}
|
|
912
|
+
|
|
913
|
+
while (stack.length > 0) {
|
|
914
|
+
const { abs, rel, depth } = stack.pop()
|
|
915
|
+
const normalizedAbs = normalizePath(abs)
|
|
916
|
+
if (seen.has(normalizedAbs)) {
|
|
917
|
+
continue
|
|
918
|
+
}
|
|
919
|
+
seen.add(normalizedAbs)
|
|
920
|
+
|
|
921
|
+
let stats
|
|
922
|
+
try {
|
|
923
|
+
stats = await fs.promises.stat(abs)
|
|
924
|
+
} catch (err) {
|
|
925
|
+
continue
|
|
926
|
+
}
|
|
927
|
+
if (!stats.isDirectory()) {
|
|
928
|
+
continue
|
|
929
|
+
}
|
|
930
|
+
|
|
931
|
+
const relPath = rel ? normalizePath(rel) : ''
|
|
932
|
+
if (relPath && shouldIgnoreRelative(relPath)) {
|
|
933
|
+
ignored.add(relPath)
|
|
934
|
+
const relSegments = relPath.split('/')
|
|
935
|
+
const lastSegment = relSegments[relSegments.length - 1]
|
|
936
|
+
if (lastSegment && ['node_modules', '.venv', 'venv', '.virtualenv', 'env'].includes(lastSegment)) {
|
|
937
|
+
autoExclude.add(relPath)
|
|
938
|
+
}
|
|
939
|
+
continue
|
|
940
|
+
}
|
|
941
|
+
|
|
942
|
+
const entries = await fs.promises.readdir(abs, { withFileTypes: true }).catch(() => [])
|
|
943
|
+
let hasPyvenvCfg = false
|
|
944
|
+
let hasExecutables = false
|
|
945
|
+
let hasSitePackages = false
|
|
946
|
+
let hasInclude = false
|
|
947
|
+
let hasNestedGit = false
|
|
948
|
+
|
|
949
|
+
for (const entry of entries) {
|
|
950
|
+
if (entry.name === '.git') {
|
|
951
|
+
let treatAsGit = false
|
|
952
|
+
if (entry.isDirectory && entry.isDirectory()) {
|
|
953
|
+
treatAsGit = true
|
|
954
|
+
} else if (entry.isFile && entry.isFile()) {
|
|
955
|
+
treatAsGit = true
|
|
956
|
+
} else if (entry.isSymbolicLink && entry.isSymbolicLink()) {
|
|
957
|
+
treatAsGit = true
|
|
958
|
+
}
|
|
959
|
+
if (treatAsGit) {
|
|
960
|
+
hasNestedGit = true
|
|
961
|
+
}
|
|
962
|
+
}
|
|
963
|
+
if (entry.isFile() && entry.name === 'pyvenv.cfg') {
|
|
964
|
+
hasPyvenvCfg = true
|
|
965
|
+
}
|
|
966
|
+
if (!entry.isDirectory()) {
|
|
967
|
+
continue
|
|
968
|
+
}
|
|
969
|
+
const lower = entry.name.toLowerCase()
|
|
970
|
+
if (lower === 'include') {
|
|
971
|
+
hasInclude = true
|
|
972
|
+
}
|
|
973
|
+
if (lower === 'bin' || lower === 'scripts') {
|
|
974
|
+
const execEntries = await fs.promises.readdir(path.join(abs, entry.name)).catch(() => [])
|
|
975
|
+
if (execEntries.some((name) => /^activate(\..*)?$/i.test(name) || /^python(\d*(\.\d+)*)?(\.exe)?$/i.test(name))) {
|
|
976
|
+
hasExecutables = true
|
|
977
|
+
}
|
|
978
|
+
}
|
|
979
|
+
if (lower === 'site-packages') {
|
|
980
|
+
hasSitePackages = true
|
|
981
|
+
}
|
|
982
|
+
if (lower === 'lib' || lower === 'lib64') {
|
|
983
|
+
const libPath = path.join(abs, entry.name)
|
|
984
|
+
const libEntries = await fs.promises.readdir(libPath, { withFileTypes: true }).catch(() => [])
|
|
985
|
+
for (const libEntry of libEntries) {
|
|
986
|
+
if (!libEntry.isDirectory()) {
|
|
987
|
+
continue
|
|
988
|
+
}
|
|
989
|
+
if (/^python\d+(\.\d+)?$/i.test(libEntry.name)) {
|
|
990
|
+
const sitePackages = path.join(libPath, libEntry.name, 'site-packages')
|
|
991
|
+
try {
|
|
992
|
+
const siteStats = await fs.promises.stat(sitePackages)
|
|
993
|
+
if (siteStats.isDirectory()) {
|
|
994
|
+
hasSitePackages = true
|
|
995
|
+
break
|
|
996
|
+
}
|
|
997
|
+
} catch (err) {}
|
|
998
|
+
}
|
|
999
|
+
if (libEntry.name === 'site-packages') {
|
|
1000
|
+
hasSitePackages = true
|
|
1001
|
+
break
|
|
1002
|
+
}
|
|
1003
|
+
}
|
|
1004
|
+
}
|
|
1005
|
+
}
|
|
1006
|
+
|
|
1007
|
+
const looksLikeVenv = hasPyvenvCfg || (hasExecutables && (hasSitePackages || hasInclude))
|
|
1008
|
+
if (looksLikeVenv && relPath) {
|
|
1009
|
+
ignored.add(relPath)
|
|
1010
|
+
autoExclude.add(relPath)
|
|
1011
|
+
continue
|
|
1012
|
+
}
|
|
1013
|
+
|
|
1014
|
+
if (hasNestedGit && relPath) {
|
|
1015
|
+
ignored.add(relPath)
|
|
1016
|
+
autoExclude.add(relPath)
|
|
1017
|
+
continue
|
|
1018
|
+
}
|
|
1019
|
+
|
|
1020
|
+
if (depth >= maxDepth) {
|
|
1021
|
+
continue
|
|
1022
|
+
}
|
|
1023
|
+
|
|
1024
|
+
for (const entry of entries) {
|
|
1025
|
+
if (!entry.isDirectory()) {
|
|
1026
|
+
continue
|
|
1027
|
+
}
|
|
1028
|
+
const childRel = rel ? `${rel}/${entry.name}` : entry.name
|
|
1029
|
+
stack.push({ abs: path.join(abs, entry.name), rel: childRel, depth: depth + 1 })
|
|
1030
|
+
}
|
|
1031
|
+
}
|
|
1032
|
+
|
|
1033
|
+
this.virtualEnvCache.set(cacheKey, { dirs: ignored, timestamp: now })
|
|
1034
|
+
if (autoExclude.size > 0) {
|
|
1035
|
+
try {
|
|
1036
|
+
await this.syncGitInfoExclude(dir, autoExclude)
|
|
1037
|
+
} catch (error) {
|
|
1038
|
+
console.warn('syncGitInfoExclude failed', dir, error)
|
|
1039
|
+
}
|
|
1040
|
+
}
|
|
1041
|
+
return ignored
|
|
1042
|
+
}
|
|
1043
|
+
async syncGitInfoExclude(dir, prefixes) {
|
|
1044
|
+
if (!prefixes || prefixes.size === 0) {
|
|
1045
|
+
return
|
|
1046
|
+
}
|
|
1047
|
+
|
|
1048
|
+
const gitdir = path.join(dir, '.git')
|
|
1049
|
+
let gitStats
|
|
1050
|
+
try {
|
|
1051
|
+
gitStats = await fs.promises.stat(gitdir)
|
|
1052
|
+
} catch (error) {
|
|
1053
|
+
return
|
|
1054
|
+
}
|
|
1055
|
+
if (!gitStats.isDirectory()) {
|
|
1056
|
+
return
|
|
1057
|
+
}
|
|
1058
|
+
|
|
1059
|
+
const infoDir = path.join(gitdir, 'info')
|
|
1060
|
+
await fs.promises.mkdir(infoDir, { recursive: true })
|
|
1061
|
+
|
|
1062
|
+
const excludePath = path.join(infoDir, 'exclude')
|
|
1063
|
+
let existing = ''
|
|
1064
|
+
try {
|
|
1065
|
+
existing = await fs.promises.readFile(excludePath, 'utf8')
|
|
1066
|
+
} catch (error) {}
|
|
1067
|
+
|
|
1068
|
+
const markerStart = '# >>> pinokiod auto-ignore >>>'
|
|
1069
|
+
const markerEnd = '# <<< pinokiod auto-ignore <<<'
|
|
1070
|
+
const lines = existing.split(/\r?\n/)
|
|
1071
|
+
const preserved = []
|
|
1072
|
+
const managed = new Set()
|
|
1073
|
+
let inBlock = false
|
|
1074
|
+
|
|
1075
|
+
for (const rawLine of lines) {
|
|
1076
|
+
const line = rawLine.trimEnd()
|
|
1077
|
+
if (line === markerStart) {
|
|
1078
|
+
inBlock = true
|
|
1079
|
+
continue
|
|
1080
|
+
}
|
|
1081
|
+
if (line === markerEnd) {
|
|
1082
|
+
inBlock = false
|
|
1083
|
+
continue
|
|
1084
|
+
}
|
|
1085
|
+
if (inBlock) {
|
|
1086
|
+
const entry = rawLine.trim()
|
|
1087
|
+
if (entry && !entry.startsWith('#')) {
|
|
1088
|
+
managed.add(entry)
|
|
1089
|
+
}
|
|
1090
|
+
continue
|
|
1091
|
+
}
|
|
1092
|
+
preserved.push(rawLine)
|
|
1093
|
+
}
|
|
1094
|
+
|
|
1095
|
+
const beforeSize = managed.size
|
|
1096
|
+
for (const prefix of prefixes) {
|
|
1097
|
+
if (!prefix) {
|
|
1098
|
+
continue
|
|
1099
|
+
}
|
|
1100
|
+
const normalized = prefix.replace(/\\/g, '/').replace(/\/+/g, '/')
|
|
1101
|
+
if (!normalized || normalized === '.git' || normalized.startsWith('.git/')) {
|
|
1102
|
+
continue
|
|
1103
|
+
}
|
|
1104
|
+
const withSlash = normalized.endsWith('/') ? normalized : `${normalized}/`
|
|
1105
|
+
managed.add(withSlash)
|
|
1106
|
+
}
|
|
1107
|
+
|
|
1108
|
+
if (managed.size === beforeSize && existing.includes(markerStart)) {
|
|
1109
|
+
return
|
|
1110
|
+
}
|
|
1111
|
+
|
|
1112
|
+
const sortedEntries = Array.from(managed)
|
|
1113
|
+
.filter(Boolean)
|
|
1114
|
+
.sort((a, b) => a.localeCompare(b))
|
|
1115
|
+
|
|
1116
|
+
const blocks = []
|
|
1117
|
+
const preservedContent = preserved.join('\n').trimEnd()
|
|
1118
|
+
if (preservedContent) {
|
|
1119
|
+
blocks.push(preservedContent)
|
|
1120
|
+
}
|
|
1121
|
+
if (sortedEntries.length > 0) {
|
|
1122
|
+
blocks.push([markerStart, ...sortedEntries, markerEnd].join('\n'))
|
|
1123
|
+
}
|
|
1124
|
+
|
|
1125
|
+
const finalContent = blocks.join('\n\n')
|
|
1126
|
+
await fs.promises.writeFile(excludePath, finalContent ? `${finalContent}\n` : '', 'utf8')
|
|
1127
|
+
}
|
|
1128
|
+
async getRepoHeadStatus(repoRelPath) {
|
|
1129
|
+
const repoParam = repoRelPath || ""
|
|
1130
|
+
const dir = repoParam ? this.kernel.path("api", repoParam) : this.kernel.path("api")
|
|
1131
|
+
|
|
1132
|
+
if (!dir) {
|
|
1133
|
+
return { changes: [], git_commit_url: null }
|
|
1134
|
+
}
|
|
1135
|
+
|
|
1136
|
+
const normalizePath = (p) => p.replace(/\\/g, '/').replace(/\/+/g, '/')
|
|
1137
|
+
const ignoredPrefixes = await this.discoverVirtualEnvDirs(dir)
|
|
1138
|
+
|
|
1139
|
+
const shouldIncludePath = (relativePath) => {
|
|
1140
|
+
if (!relativePath) {
|
|
1141
|
+
return true
|
|
1142
|
+
}
|
|
1143
|
+
const normalized = normalizePath(relativePath)
|
|
1144
|
+
if (this.gitStatusIgnorePatterns && this.gitStatusIgnorePatterns.some((regex) => regex.test(normalized) || regex.test(`${normalized}/`))) {
|
|
1145
|
+
return false
|
|
1146
|
+
}
|
|
1147
|
+
for (const prefix of ignoredPrefixes) {
|
|
1148
|
+
if (normalized === prefix || normalized.startsWith(`${prefix}/`)) {
|
|
1149
|
+
return false
|
|
1150
|
+
}
|
|
1151
|
+
}
|
|
1152
|
+
if (normalized.includes('/site-packages/')) {
|
|
1153
|
+
return false
|
|
1154
|
+
}
|
|
1155
|
+
if (normalized.includes('/Scripts/')) {
|
|
1156
|
+
return false
|
|
1157
|
+
}
|
|
1158
|
+
if (normalized.includes('/bin/activate')) {
|
|
1159
|
+
return false
|
|
1160
|
+
}
|
|
1161
|
+
return true
|
|
1162
|
+
}
|
|
1163
|
+
|
|
1164
|
+
let statusMatrix = await git.statusMatrix({ dir, fs })
|
|
1165
|
+
statusMatrix = statusMatrix.filter(Boolean)
|
|
1166
|
+
|
|
1167
|
+
const changes = []
|
|
1168
|
+
for (const [filepath, head, workdir, stage] of statusMatrix) {
|
|
1169
|
+
if (!shouldIncludePath(filepath)) {
|
|
1170
|
+
continue
|
|
1171
|
+
}
|
|
1172
|
+
if (head === workdir && head === stage) {
|
|
1173
|
+
continue
|
|
1174
|
+
}
|
|
1175
|
+
const absolutePath = path.join(dir, filepath)
|
|
1176
|
+
let stats
|
|
1177
|
+
try {
|
|
1178
|
+
stats = await fs.promises.stat(absolutePath)
|
|
1179
|
+
} catch (error) {
|
|
1180
|
+
stats = null
|
|
1181
|
+
}
|
|
1182
|
+
if (stats && stats.isDirectory()) {
|
|
1183
|
+
continue
|
|
1184
|
+
}
|
|
1185
|
+
|
|
1186
|
+
const status = Util.classifyChange(head, workdir, stage)
|
|
1187
|
+
if (!status) {
|
|
1188
|
+
continue
|
|
1189
|
+
}
|
|
1190
|
+
|
|
1191
|
+
const webpath = "/asset/" + path.relative(this.kernel.homedir, absolutePath)
|
|
1192
|
+
|
|
1193
|
+
changes.push({
|
|
1194
|
+
ref: 'HEAD',
|
|
1195
|
+
webpath,
|
|
1196
|
+
file: normalizePath(filepath),
|
|
1197
|
+
path: absolutePath,
|
|
1198
|
+
diffpath: `/gitdiff/HEAD/${repoParam}/${normalizePath(filepath)}`,
|
|
1199
|
+
status,
|
|
1200
|
+
})
|
|
1201
|
+
}
|
|
1202
|
+
|
|
1203
|
+
const repoHistoryUrl = repoParam ? `/info/git/HEAD/${repoParam}` : null
|
|
1204
|
+
|
|
1205
|
+
return {
|
|
1206
|
+
changes,
|
|
1207
|
+
git_commit_url: `/run/scripts/git/commit.json?cwd=${dir}&callback_target=parent&callback=$location.href`,
|
|
1208
|
+
git_history_url: repoHistoryUrl,
|
|
1209
|
+
}
|
|
1210
|
+
}
|
|
1211
|
+
async computeWorkspaceGitStatus(workspaceName) {
|
|
1212
|
+
const workspacePath = this.kernel.path("api", workspaceName)
|
|
1213
|
+
const repos = await this.kernel.git.repos(workspacePath)
|
|
1214
|
+
|
|
1215
|
+
// await Util.ignore_subrepos(workspacePath, repos)
|
|
1216
|
+
|
|
1217
|
+
const statuses = []
|
|
1218
|
+
for (const repo of repos) {
|
|
1219
|
+
const repoParam = repo.gitParentRelPath || workspaceName
|
|
1220
|
+
try {
|
|
1221
|
+
const { changes, git_commit_url, git_history_url } = await this.getRepoHeadStatus(repoParam)
|
|
1222
|
+
const historyUrl = git_history_url || (repoParam ? `/info/git/HEAD/${repoParam}` : `/info/git/HEAD/${workspaceName}`)
|
|
1223
|
+
statuses.push({
|
|
1224
|
+
name: repo.name,
|
|
1225
|
+
main: repo.main,
|
|
1226
|
+
gitParentRelPath: repo.gitParentRelPath,
|
|
1227
|
+
repoParam,
|
|
1228
|
+
changeCount: changes.length,
|
|
1229
|
+
changes,
|
|
1230
|
+
git_commit_url,
|
|
1231
|
+
git_history_url: historyUrl,
|
|
1232
|
+
url: repo.url || null,
|
|
1233
|
+
})
|
|
1234
|
+
} catch (error) {
|
|
1235
|
+
console.error('computeWorkspaceGitStatus error', repoParam, error)
|
|
1236
|
+
const historyUrl = repoParam ? `/info/git/HEAD/${repoParam}` : `/info/git/HEAD/${workspaceName}`
|
|
1237
|
+
statuses.push({
|
|
1238
|
+
name: repo.name,
|
|
1239
|
+
main: repo.main,
|
|
1240
|
+
gitParentRelPath: repo.gitParentRelPath,
|
|
1241
|
+
repoParam,
|
|
1242
|
+
changeCount: 0,
|
|
1243
|
+
changes: [],
|
|
1244
|
+
git_commit_url: null,
|
|
1245
|
+
git_history_url: historyUrl,
|
|
1246
|
+
url: repo.url || null,
|
|
1247
|
+
error: error ? String(error.message || error) : 'unknown',
|
|
1248
|
+
})
|
|
1249
|
+
}
|
|
1250
|
+
}
|
|
1251
|
+
|
|
1252
|
+
const totalChanges = statuses.reduce((sum, repo) => sum + (repo.changeCount || 0), 0)
|
|
1253
|
+
return { totalChanges, repos: statuses }
|
|
1254
|
+
}
|
|
872
1255
|
async render(req, res, pathComponents, meta) {
|
|
873
1256
|
let base_path = req.base || this.kernel.path("api")
|
|
874
1257
|
let full_filepath = path.resolve(base_path, ...pathComponents)
|
|
@@ -5417,35 +5800,8 @@ class Server {
|
|
|
5417
5800
|
let d = Date.now()
|
|
5418
5801
|
let changes = []
|
|
5419
5802
|
if (req.params.ref === "HEAD") {
|
|
5420
|
-
|
|
5421
|
-
|
|
5422
|
-
statusMatrix = statusMatrix.filter(Boolean);
|
|
5423
|
-
for (const [filepath, head, workdir, stage] of statusMatrix) {
|
|
5424
|
-
if (head !== workdir || head !== stage) {
|
|
5425
|
-
const fullPath = path.join(dir, filepath);
|
|
5426
|
-
let relpath = path.relative(this.kernel.homedir, fullPath)
|
|
5427
|
-
let webpath = "/asset/" + relpath
|
|
5428
|
-
let rel_filepath = path.relative(this.kernel.path("api"), fullPath)
|
|
5429
|
-
|
|
5430
|
-
const stats = await fs.promises.stat(fullPath)
|
|
5431
|
-
if (stats.isDirectory()) {
|
|
5432
|
-
continue
|
|
5433
|
-
}
|
|
5434
|
-
|
|
5435
|
-
|
|
5436
|
-
changes.push({
|
|
5437
|
-
ref: req.params.ref,
|
|
5438
|
-
webpath,
|
|
5439
|
-
file: filepath,
|
|
5440
|
-
path: fullPath,
|
|
5441
|
-
diffpath: `/gitdiff/${req.params.ref}/${req.params[0]}/${filepath}`,
|
|
5442
|
-
status: Util.classifyChange(head, workdir, stage),
|
|
5443
|
-
});
|
|
5444
|
-
}
|
|
5445
|
-
}
|
|
5446
|
-
} catch (err) {
|
|
5447
|
-
// console.log("git status matrix error 1", err)
|
|
5448
|
-
}
|
|
5803
|
+
const { changes: headChanges, git_commit_url } = await this.getRepoHeadStatus(req.params[0])
|
|
5804
|
+
return res.json({ git_commit_url, changes: headChanges })
|
|
5449
5805
|
} else {
|
|
5450
5806
|
try {
|
|
5451
5807
|
let ref = req.params.ref
|
|
@@ -5591,6 +5947,15 @@ class Server {
|
|
|
5591
5947
|
let response = await this.getGit(req.params.ref, req.params[0])
|
|
5592
5948
|
res.json(response)
|
|
5593
5949
|
}))
|
|
5950
|
+
this.app.get("/info/gitstatus/:name", ex(async (req, res) => {
|
|
5951
|
+
try {
|
|
5952
|
+
const data = await this.computeWorkspaceGitStatus(req.params.name)
|
|
5953
|
+
res.json(data)
|
|
5954
|
+
} catch (error) {
|
|
5955
|
+
console.error('[git-status] compute error', req.params.name, error)
|
|
5956
|
+
res.status(500).json({ totalChanges: 0, repos: [], error: error ? String(error.message || error) : 'unknown' })
|
|
5957
|
+
}
|
|
5958
|
+
}))
|
|
5594
5959
|
this.app.get("/git/:ref/*", ex(async (req, res) => {
|
|
5595
5960
|
|
|
5596
5961
|
let { requirements, install_required, requirements_pending, error } = await this.kernel.bin.check({
|
|
@@ -5904,7 +6269,7 @@ class Server {
|
|
|
5904
6269
|
let c = this.kernel.path("api", req.params.name)
|
|
5905
6270
|
let repos = await this.kernel.git.repos(c)
|
|
5906
6271
|
|
|
5907
|
-
await Util.ignore_subrepos(c, repos)
|
|
6272
|
+
// await Util.ignore_subrepos(c, repos)
|
|
5908
6273
|
|
|
5909
6274
|
// check if these are in the existing .git
|
|
5910
6275
|
//
|
|
@@ -6239,7 +6604,7 @@ class Server {
|
|
|
6239
6604
|
title: name,
|
|
6240
6605
|
url: gitRemote,
|
|
6241
6606
|
//redirect_uri: "http://localhost:3001/apps/redirect?git=" + gitRemote,
|
|
6242
|
-
redirect_uri: "https://
|
|
6607
|
+
redirect_uri: "https://pinokio.co/apps/redirect?git=" + gitRemote,
|
|
6243
6608
|
platform: this.kernel.platform,
|
|
6244
6609
|
theme: this.theme,
|
|
6245
6610
|
agent: req.agent,
|