@hsusulist/luc 0.2.4 → 0.3.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/README.md CHANGED
@@ -1,14 +1,19 @@
1
1
  # @hsusulist/luc
2
2
 
3
- Install and launch the [LUC](https://github.com/hsusulist/luc) language on Windows.
3
+ Install and launch the [LUC](https://github.com/hsusulist/luc) language on Windows or Linux.
4
4
 
5
5
  ```powershell
6
6
  npm install -g @hsusulist/luc
7
7
  luc --version
8
8
  ```
9
9
 
10
- The package installs the runtime into `%LOCALAPPDATA%\Programs\LUC` (no PATH
11
- changes, no admin rights). If the automatic install is skipped, run:
10
+ On Linux, the package compiles the runtime during installation. Install a C
11
+ compiler such as GCC or Clang first; set `CC` if your compiler is not named
12
+ `cc`. `luc --install` rebuilds the native runtime.
13
+
14
+ On Windows, the package installs the runtime into
15
+ `%LOCALAPPDATA%\Programs\LUC` (no PATH changes, no admin rights). If the
16
+ automatic install is skipped, run:
12
17
 
13
18
  ```powershell
14
19
  luc --install
@@ -23,9 +28,14 @@ luc --install -c window,ai -d "D:\Tools\LUC" -y
23
28
  ```
24
29
 
25
30
  Available components: `window`, `ai`, `discord`, `lcode`, `vscode`, `source`.
26
- LCode is optional and is not selected by default. To install its launcher from
27
- npm instead, use `npm install -g @hsusulist/lcode`.
31
+ LCode is optional and is not selected by default. Selecting it installs
32
+ `lcode.exe` alongside the interpreter. To install only the editor without the
33
+ LUC command, use `npm install -g @hsusulist/lcode`.
34
+
35
+ On Windows, the npm package is a small launcher; the runtime is downloaded from
36
+ the signed GitHub release and verified with SHA-256 and Ed25519 (minisign
37
+ format) before it is installed. On Linux, the package builds from its bundled
38
+ LUC and LCode C sources.
28
39
 
29
- The npm package is a small launcher; the runtime is downloaded from the signed
30
- GitHub release and verified with SHA-256 and Ed25519 (minisign format) before it
31
- is installed.
40
+ The editor-only package uses the separate, signed `lcode-portable.zip` release
41
+ asset on Windows. On Linux it compiles the included native terminal editor.
package/bin/luc.js CHANGED
@@ -6,6 +6,28 @@ const os = require('os');
6
6
  const path = require('path');
7
7
  const { spawnSync } = require('child_process');
8
8
 
9
+ const args = process.argv.slice(2);
10
+
11
+ if (process.platform === 'linux') {
12
+ const packageDir = path.join(__dirname, '..');
13
+ const { buildLinux } = require('../scripts/build-linux');
14
+ if (args[0] === '--install') {
15
+ buildLinux(packageDir, 'luc');
16
+ process.exit(0);
17
+ }
18
+ const binary = path.join(packageDir, 'native', 'luc');
19
+ if (!fs.existsSync(binary)) {
20
+ console.error('luc: Linux runtime is missing; run "luc --install" to build it.');
21
+ process.exit(1);
22
+ }
23
+ const result = spawnSync(binary, args, { stdio: 'inherit' });
24
+ if (result.error) {
25
+ console.error('luc: ' + result.error.message);
26
+ process.exit(1);
27
+ }
28
+ process.exit(result.status === null ? 1 : result.status);
29
+ }
30
+
9
31
  function stateBinary() {
10
32
  const local = process.env.LOCALAPPDATA || path.join(os.homedir(), 'AppData', 'Local');
11
33
  try {
@@ -95,11 +117,10 @@ function mapInstallerArgs(args) {
95
117
  }
96
118
 
97
119
  if (process.platform !== 'win32') {
98
- console.error('luc: this package currently supports Windows only.');
120
+ console.error('luc: this package supports Windows and Linux only.');
99
121
  process.exit(1);
100
122
  }
101
123
 
102
- const args = process.argv.slice(2);
103
124
  let binary = findBinary();
104
125
 
105
126
  if (!binary) {
package/install.ps1 CHANGED
@@ -10,6 +10,7 @@ param(
10
10
  [switch]$NoEnvironmentChanges,
11
11
  [switch]$Force,
12
12
  [switch]$Quiet,
13
+ [switch]$LCodeOnly,
13
14
  [switch]$AllowUnsigned,
14
15
  [switch]$NoColor
15
16
  )
@@ -20,7 +21,7 @@ Add-Type -AssemblyName System.IO.Compression.FileSystem
20
21
 
21
22
  $repo = 'hsusulist/luc'
22
23
  $minisignPublicKey = 'RWRPLJnLdrwqwkmhtMPAEfihwSnAC9TmbPc4ghGntXYOSLqKlKGUUx40'
23
- $defaultInstallPath = Join-Path $env:LOCALAPPDATA 'Programs\LUC'
24
+ $defaultInstallPath = Join-Path $env:LOCALAPPDATA $(if ($LCodeOnly) { 'Programs\LCode' } else { 'Programs\LUC' })
24
25
  $optionalComponents = @('window', 'ai', 'discord', 'lcode', 'vscode', 'source')
25
26
  $componentInfo = [ordered]@{
26
27
  window = @{ Label = 'Window support'; Desc = 'SDL2 graphics, sound and the Pong demo' }
@@ -464,16 +465,19 @@ function Get-ArchivePlan {
464
465
  [IO.Compression.ZipArchive]$Zip,
465
466
  [string[]]$SelectedComponents,
466
467
  [string]$Target,
467
- [string]$VsCodeTarget
468
+ [string]$VsCodeTarget,
469
+ [switch]$LCodeOnly
468
470
  )
469
471
 
470
472
  if ($Zip.Entries.Count -gt $maxEntries) {
471
473
  throw "Archive contains too many entries ($($Zip.Entries.Count) > $maxEntries)."
472
474
  }
473
475
 
474
- $prefixes = @('core', 'common')
476
+ $prefixes = @()
477
+ if ($LCodeOnly) { $prefixes += 'lcode' }
478
+ else { $prefixes += @('core', 'common') }
475
479
  foreach ($name in $SelectedComponents) {
476
- if ($name -ne 'core') { $prefixes += $name }
480
+ if ($name -ne 'core' -and $prefixes -notcontains $name) { $prefixes += $name }
477
481
  }
478
482
 
479
483
  $plan = New-Object System.Collections.Generic.List[object]
@@ -913,7 +917,7 @@ function Add-UserPath {
913
917
  }
914
918
 
915
919
  function Write-InstallState {
916
- param([string]$Version, [string]$Path, [string[]]$Selected, [string]$SourceName)
920
+ param([string]$Version, [string]$Path, [string[]]$Selected, [string]$SourceName, [switch]$LCodeOnly)
917
921
  $stateDir = Join-Path $env:LOCALAPPDATA 'LUC'
918
922
  if (-not (Test-Path -LiteralPath $stateDir -PathType Container)) {
919
923
  New-Item -ItemType Directory -Force -Path $stateDir | Out-Null
@@ -921,22 +925,24 @@ function Write-InstallState {
921
925
  $state = [ordered]@{
922
926
  version = $Version
923
927
  installPath = $Path
924
- components = @('core') + $Selected
928
+ components = if ($LCodeOnly) { @('lcode') } else { @('core') + $Selected }
925
929
  source = $SourceName
926
930
  installedAt = (Get-Date).ToString('o')
927
931
  }
928
- $state | ConvertTo-Json -Depth 4 | Set-Content -LiteralPath (Join-Path $stateDir 'state.json') -Encoding UTF8
932
+ $stateFile = if ($LCodeOnly) { 'lcode-state.json' } else { 'state.json' }
933
+ $state | ConvertTo-Json -Depth 4 | Set-Content -LiteralPath (Join-Path $stateDir $stateFile) -Encoding UTF8
929
934
  }
930
935
 
931
936
  function Write-InstallManifest {
932
- param([string]$Version, [string]$Path, [string[]]$Selected)
937
+ param([string]$Version, [string]$Path, [string[]]$Selected, [switch]$LCodeOnly)
933
938
  $manifest = [ordered]@{
934
939
  version = $Version
935
- components = @('core') + $Selected
940
+ components = if ($LCodeOnly) { @('lcode') } else { @('core') + $Selected }
936
941
  installedAt = (Get-Date).ToString('o')
937
942
  }
938
943
  try {
939
- $manifest | ConvertTo-Json -Depth 4 | Set-Content -LiteralPath (Join-Path $Path '.luc-manifest.json') -Encoding UTF8
944
+ $manifestFile = if ($LCodeOnly) { '.lcode-manifest.json' } else { '.luc-manifest.json' }
945
+ $manifest | ConvertTo-Json -Depth 4 | Set-Content -LiteralPath (Join-Path $Path $manifestFile) -Encoding UTF8
940
946
  } catch {
941
947
  Write-Note "Could not write the install manifest: $($_.Exception.Message)" 'warn'
942
948
  }
@@ -977,7 +983,8 @@ try {
977
983
  if ($Source -eq 'local' -and -not $ArchivePath) {
978
984
  if (-not $script:Interactive) { throw 'A local install needs -ArchivePath pointing at luc-portable.zip.' }
979
985
  Enter-AltScreen
980
- $ArchivePath = Show-PathPage -Title 'Portable archive (.zip)' -Default (Join-Path $env:USERPROFILE 'Downloads\luc-portable.zip') -ExistingFile
986
+ $archiveName = if ($LCodeOnly) { 'lcode-portable.zip' } else { 'luc-portable.zip' }
987
+ $ArchivePath = Show-PathPage -Title 'Portable archive (.zip)' -Default (Join-Path $env:USERPROFILE "Downloads\$archiveName") -ExistingFile
981
988
  Exit-AltScreen
982
989
  if (-not $ArchivePath) { Write-Note 'Installation cancelled.' 'warn'; exit 2 }
983
990
  }
@@ -1011,11 +1018,12 @@ try {
1011
1018
  $script:Version = $release.tag_name -replace '^v', ''
1012
1019
 
1013
1020
  $assets = @($release.assets)
1014
- $zipAsset = $assets | Where-Object { $_.name -eq 'luc-portable.zip' } | Select-Object -First 1
1015
- $hashAsset = $assets | Where-Object { $_.name -eq 'luc-portable.zip.sha256' } | Select-Object -First 1
1016
- $sigAsset = $assets | Where-Object { $_.name -eq 'luc-portable.zip.sha256.minisig' } | Select-Object -First 1
1021
+ $archiveName = if ($LCodeOnly) { 'lcode-portable.zip' } else { 'luc-portable.zip' }
1022
+ $zipAsset = $assets | Where-Object { $_.name -eq $archiveName } | Select-Object -First 1
1023
+ $hashAsset = $assets | Where-Object { $_.name -eq "$archiveName.sha256" } | Select-Object -First 1
1024
+ $sigAsset = $assets | Where-Object { $_.name -eq "$archiveName.sha256.minisig" } | Select-Object -First 1
1017
1025
  if (-not $zipAsset -or -not $hashAsset) {
1018
- throw "Release $($release.tag_name) must include luc-portable.zip and luc-portable.zip.sha256."
1026
+ throw "Release $($release.tag_name) must include $archiveName and $archiveName.sha256."
1019
1027
  }
1020
1028
  Assert-ReleaseUrl $zipAsset.browser_download_url $zipAsset.name
1021
1029
  Assert-ReleaseUrl $hashAsset.browser_download_url $hashAsset.name
@@ -1023,7 +1031,7 @@ try {
1023
1031
 
1024
1032
  $downloadTemp = Join-Path ([IO.Path]::GetTempPath()) ('luc-install-' + [guid]::NewGuid().ToString('N'))
1025
1033
  New-Item -ItemType Directory -Force -Path $downloadTemp | Out-Null
1026
- $archiveFile = Join-Path $downloadTemp 'luc-portable.zip'
1034
+ $archiveFile = Join-Path $downloadTemp $archiveName
1027
1035
  $checksumFile = "$archiveFile.sha256"
1028
1036
  $signatureFile = "$checksumFile.minisig"
1029
1037
  Invoke-Download $zipAsset.browser_download_url $archiveFile 'portable archive'
@@ -1068,13 +1076,13 @@ try {
1068
1076
  throw 'The downloaded archive version does not match its GitHub release tag.'
1069
1077
  }
1070
1078
  $script:Version = $archiveVersion
1071
- if (-not $Quiet) { Write-Note "LUC $($script:Version) verified" 'ok' }
1079
+ if (-not $Quiet) { Write-Note "$(if ($LCodeOnly) { 'LCode' } else { 'LUC' }) $($script:Version) verified" 'ok' }
1072
1080
 
1073
1081
  $licenseText = Read-ZipEntryText $zip 'LICENCE'
1074
1082
  if (-not $licenseText) { $licenseText = 'LUC is free software released under the Apache License 2.0.' }
1075
1083
 
1076
- $selected = @()
1077
- if ($Components) {
1084
+ $selected = if ($LCodeOnly) { @('lcode') } else { @() }
1085
+ if (-not $LCodeOnly -and $Components) {
1078
1086
  foreach ($item in $Components) {
1079
1087
  foreach ($name in ($item -split '[,\s]+')) {
1080
1088
  if ([string]::IsNullOrWhiteSpace($name)) { continue }
@@ -1086,7 +1094,7 @@ try {
1086
1094
  }
1087
1095
  }
1088
1096
 
1089
- if ($script:Interactive -and -not $Components) {
1097
+ if (-not $LCodeOnly -and $script:Interactive -and -not $Components) {
1090
1098
  Enter-AltScreen
1091
1099
  $picked = Show-ComponentPage -Preselected $selected -LicenseText $licenseText
1092
1100
  Exit-AltScreen
@@ -1108,9 +1116,10 @@ try {
1108
1116
  }
1109
1117
 
1110
1118
  $vsCodeTarget = Join-Path $env:USERPROFILE '.vscode\extensions\hsusulist.luc'
1111
- $upgrade = Test-Path -LiteralPath (Join-Path $InstallPath 'luc.exe') -PathType Leaf
1119
+ $binaryName = if ($LCodeOnly) { 'lcode.exe' } else { 'luc.exe' }
1120
+ $upgrade = Test-Path -LiteralPath (Join-Path $InstallPath $binaryName) -PathType Leaf
1112
1121
  if ($upgrade -and -not $Force -and -not $Yes -and -not $script:Interactive) {
1113
- throw "LUC is already installed in '$InstallPath'. Pass -Force to replace it."
1122
+ throw "$binaryName is already installed in '$InstallPath'. Pass -Force to replace it."
1114
1123
  }
1115
1124
 
1116
1125
  if ($script:Interactive) {
@@ -1135,9 +1144,9 @@ try {
1135
1144
  }
1136
1145
 
1137
1146
  $script:StagingRoot = Join-Path (Split-Path -Parent $InstallPath) ('.luc-staging-' + [guid]::NewGuid().ToString('N'))
1138
- $archivePlan = Get-ArchivePlan -Zip $zip -SelectedComponents $selected -Target $InstallPath -VsCodeTarget $vsCodeTarget
1139
- if (-not ($archivePlan.Items | Where-Object { $_.Relative -eq 'luc.exe' -and $_.Destination -eq (Join-Path $InstallPath 'luc.exe') })) {
1140
- throw 'Core installation did not produce luc.exe.'
1147
+ $archivePlan = Get-ArchivePlan -Zip $zip -SelectedComponents $selected -Target $InstallPath -VsCodeTarget $vsCodeTarget -LCodeOnly:$LCodeOnly
1148
+ if (-not ($archivePlan.Items | Where-Object { $_.Relative -eq $binaryName -and $_.Destination -eq (Join-Path $InstallPath $binaryName) })) {
1149
+ throw "Installation archive did not produce $binaryName."
1141
1150
  }
1142
1151
 
1143
1152
  $roots = @($InstallPath)
@@ -1159,31 +1168,33 @@ try {
1159
1168
  Install-ArchivePlan $archivePlan.Items
1160
1169
  Write-StepDone 'Files installed'
1161
1170
 
1162
- if (-not (Test-Path -LiteralPath (Join-Path $InstallPath 'luc.exe') -PathType Leaf)) {
1163
- throw 'Installation finished without luc.exe. The previous version was restored.'
1171
+ if (-not (Test-Path -LiteralPath (Join-Path $InstallPath $binaryName) -PathType Leaf)) {
1172
+ throw "Installation finished without $binaryName. The previous version was restored."
1164
1173
  }
1165
1174
 
1166
- Write-InstallManifest $script:Version $InstallPath $selected
1167
- Write-InstallState $script:Version $InstallPath $selected $Source
1175
+ Write-InstallManifest $script:Version $InstallPath $selected -LCodeOnly:$LCodeOnly
1176
+ Write-InstallState $script:Version $InstallPath $selected $Source -LCodeOnly:$LCodeOnly
1168
1177
 
1169
1178
  # Keep a copy of this script next to luc.exe so that "luc --install" works
1170
1179
  # even when the archive was built before install.ps1 was bundled in it.
1171
- try {
1172
- $selfScript = $PSCommandPath
1173
- if (-not $selfScript) { $selfScript = $MyInvocation.MyCommand.Path }
1174
- $targetScript = Join-Path $InstallPath 'install.ps1'
1175
- if ($selfScript -and (Test-Path -LiteralPath $selfScript -PathType Leaf) -and
1176
- -not [string]::Equals($selfScript, $targetScript, [StringComparison]::OrdinalIgnoreCase)) {
1177
- Copy-Item -LiteralPath $selfScript -Destination $targetScript -Force
1180
+ if (-not $LCodeOnly) {
1181
+ try {
1182
+ $selfScript = $PSCommandPath
1183
+ if (-not $selfScript) { $selfScript = $MyInvocation.MyCommand.Path }
1184
+ $targetScript = Join-Path $InstallPath 'install.ps1'
1185
+ if ($selfScript -and (Test-Path -LiteralPath $selfScript -PathType Leaf) -and
1186
+ -not [string]::Equals($selfScript, $targetScript, [StringComparison]::OrdinalIgnoreCase)) {
1187
+ Copy-Item -LiteralPath $selfScript -Destination $targetScript -Force
1188
+ }
1189
+ } catch {
1190
+ Write-Note "Could not copy install.ps1 next to luc.exe: $($_.Exception.Message)" 'warn'
1178
1191
  }
1179
- } catch {
1180
- Write-Note "Could not copy install.ps1 next to luc.exe: $($_.Exception.Message)" 'warn'
1181
1192
  }
1182
1193
 
1183
1194
  Remove-StaleBackups $InstallPath
1184
1195
  if ($selected -contains 'vscode') { Remove-StaleBackups $vsCodeTarget }
1185
1196
 
1186
- if (-not $NoEnvironmentChanges) {
1197
+ if (-not $NoEnvironmentChanges -and -not $LCodeOnly) {
1187
1198
  [Environment]::SetEnvironmentVariable('LUC_PATH', (Join-Path $InstallPath 'luc_modules'), 'User')
1188
1199
  if (-not $NoPath) {
1189
1200
  $addPath = $true
@@ -1197,8 +1208,10 @@ try {
1197
1208
  }
1198
1209
 
1199
1210
  Write-Host ''
1200
- Write-Host "LUC $($script:Version) installed to $InstallPath" -ForegroundColor Green
1201
- Write-Host 'Open a new terminal, then run: luc --help'
1211
+ $productName = if ($LCodeOnly) { 'LCode' } else { 'LUC' }
1212
+ Write-Host "$productName $($script:Version) installed to $InstallPath" -ForegroundColor Green
1213
+ if ($LCodeOnly) { Write-Host 'Open a new terminal, then run: lcode .' }
1214
+ else { Write-Host 'Open a new terminal, then run: luc --help' }
1202
1215
  exit 0
1203
1216
  } catch {
1204
1217
  if ($script:InAltScreen) { Exit-AltScreen }
package/package.json CHANGED
@@ -1,13 +1,14 @@
1
1
  {
2
2
  "name": "@hsusulist/luc",
3
- "version": "0.2.4",
4
- "description": "LUC language installer and launcher for Windows",
3
+ "version": "0.3.0",
4
+ "description": "LUC language installer and launcher",
5
5
  "bin": {
6
6
  "luc": "bin/luc.js"
7
7
  },
8
8
  "files": [
9
9
  "bin",
10
10
  "scripts",
11
+ "src",
11
12
  "install.ps1",
12
13
  "LICENCE",
13
14
  "README.md"
@@ -17,9 +18,7 @@
17
18
  "postpack": "node scripts/postpack.js",
18
19
  "postinstall": "node scripts/postinstall.js"
19
20
  },
20
- "os": [
21
- "win32"
22
- ],
21
+ "os": ["win32", "linux"],
23
22
  "engines": {
24
23
  "node": ">=16"
25
24
  },
@@ -0,0 +1,34 @@
1
+ 'use strict';
2
+
3
+ const fs = require('fs');
4
+ const path = require('path');
5
+ const { spawnSync } = require('child_process');
6
+
7
+ function buildLinux(packageDir, name) {
8
+ const sourceDir = path.join(packageDir, 'src');
9
+ const files = ['luc_core.c', 'luc_libs.c', 'luc_trans.c'].map((file) =>
10
+ path.join(sourceDir, file)
11
+ );
12
+ for (const file of files) {
13
+ if (!fs.existsSync(file)) {
14
+ throw new Error('Linux source is missing from this npm package: ' + file);
15
+ }
16
+ }
17
+
18
+ const outputDir = path.join(packageDir, 'native');
19
+ const output = path.join(outputDir, name);
20
+ fs.mkdirSync(outputDir, { recursive: true });
21
+
22
+ const compiler = process.env.CC || 'cc';
23
+ const args = ['-O2', '-std=gnu99', '-o', output].concat(files, ['-lm', '-ldl']);
24
+ const result = spawnSync(compiler, args, { stdio: 'inherit' });
25
+ if (result.error) {
26
+ throw new Error('could not start ' + compiler + ' to build LUC: ' + result.error.message);
27
+ }
28
+ if (result.status !== 0) {
29
+ throw new Error(compiler + ' failed to build LUC (exit code ' + result.status + ').');
30
+ }
31
+ return output;
32
+ }
33
+
34
+ module.exports = { buildLinux };
@@ -5,6 +5,12 @@ const os = require('os');
5
5
  const path = require('path');
6
6
  const { spawnSync } = require('child_process');
7
7
 
8
+ if (process.platform === 'linux') {
9
+ const { buildLinux } = require('./build-linux');
10
+ buildLinux(path.join(__dirname, '..'), 'luc');
11
+ process.exit(0);
12
+ }
13
+
8
14
  function findBinary() {
9
15
  const candidates = [];
10
16
  const local = process.env.LOCALAPPDATA || path.join(os.homedir(), 'AppData', 'Local');
@@ -5,7 +5,21 @@ const path = require('path');
5
5
 
6
6
  for (const name of ['install.ps1', 'LICENCE']) {
7
7
  try {
8
- fs.unlinkSync(path.join(__dirname, '..', name));
8
+ fs.unlinkSync(path.join(process.cwd(), name));
9
9
  } catch (_) {
10
10
  }
11
11
  }
12
+
13
+ const source = path.join(process.cwd(), 'src');
14
+ const marker = path.join(process.cwd(), '.npm-source-bundle-generated');
15
+ if (fs.existsSync(marker)) {
16
+ fs.rmSync(source, { recursive: true, force: true });
17
+ fs.unlinkSync(marker);
18
+ }
19
+
20
+ const helper = path.join(process.cwd(), 'scripts', 'build-linux.js');
21
+ const helperMarker = path.join(process.cwd(), '.npm-build-linux-generated');
22
+ if (fs.existsSync(helperMarker)) {
23
+ fs.unlinkSync(helper);
24
+ fs.unlinkSync(helperMarker);
25
+ }
@@ -4,7 +4,7 @@ const fs = require('fs');
4
4
  const path = require('path');
5
5
 
6
6
  const root = path.join(__dirname, '..', '..');
7
- const here = path.join(__dirname, '..');
7
+ const here = process.cwd();
8
8
 
9
9
  function copy(name) {
10
10
  const source = path.join(root, name);
@@ -17,3 +17,30 @@ function copy(name) {
17
17
 
18
18
  copy('install.ps1');
19
19
  copy('LICENCE');
20
+
21
+ const source = path.join(root, 'src');
22
+ const target = path.join(here, 'src');
23
+ if (fs.existsSync(target)) {
24
+ throw new Error('refusing to overwrite existing npm/src directory');
25
+ }
26
+ fs.mkdirSync(target);
27
+ for (const name of ['luc_core.c', 'luc_libs.c', 'luc_trans.c', 'luc.h']) {
28
+ const from = path.join(source, name);
29
+ if (!fs.existsSync(from)) throw new Error('missing release source: ' + from);
30
+ fs.copyFileSync(from, path.join(target, name));
31
+ }
32
+ const linuxEditor = path.join(source, 'lcode-linux', 'lcode.c');
33
+ if (!fs.existsSync(linuxEditor)) throw new Error('missing Linux editor source: ' + linuxEditor);
34
+ fs.mkdirSync(path.join(target, 'lcode-linux'));
35
+ fs.copyFileSync(linuxEditor, path.join(target, 'lcode-linux', 'lcode.c'));
36
+ fs.writeFileSync(path.join(here, '.npm-source-bundle-generated'), 'generated by prepack\n');
37
+
38
+ const helper = path.join(__dirname, 'build-linux.js');
39
+ const packagedHelper = path.join(here, 'scripts', 'build-linux.js');
40
+ if (helper !== packagedHelper) {
41
+ if (fs.existsSync(packagedHelper)) {
42
+ throw new Error('refusing to overwrite existing scripts/build-linux.js');
43
+ }
44
+ fs.copyFileSync(helper, packagedHelper);
45
+ fs.writeFileSync(path.join(here, '.npm-build-linux-generated'), 'generated by prepack\n');
46
+ }