Skip to content
This repository was archived by the owner on Feb 15, 2023. It is now read-only.

Commit cf31fa2

Browse files
committed
🚧 Copy template as part of setup process
1 parent 4969544 commit cf31fa2

File tree

19 files changed

+424
-76
lines changed

19 files changed

+424
-76
lines changed

β€Ž.gitignoreβ€Ž

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,3 +102,5 @@ dist
102102

103103
# TernJS port file
104104
.tern-port
105+
106+
testing/

β€Žsrc/commands/setupProject.tsβ€Ž

Lines changed: 144 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -1,87 +1,163 @@
1-
import { writeFileSync, existsSync } from 'fs'
1+
import { writeFileSync, existsSync, mkdirSync } from 'fs'
2+
import { readdir, stat, copyFile } from 'fs/promises'
3+
import { join, isAbsolute, dirname } from 'path'
24

35
import prompts from 'prompts'
46

57
import { log } from '..'
6-
import { Config, configPath, getLatestFF, SupportedProducts } from '../utils'
8+
import {
9+
Config,
10+
configPath,
11+
getLatestFF,
12+
projectDir,
13+
SupportedProducts,
14+
} from '../utils'
715

8-
const sleep = (time: number) => new Promise<void>((r) => setTimeout(r, time))
16+
// =============================================================================
17+
// User interaction portion
918

1019
export async function setupProject() {
11-
if (existsSync(configPath)) {
12-
log.warning('There is already a config file. This will overwrite it!')
13-
await sleep(1000)
14-
}
20+
try {
21+
if (existsSync(configPath)) {
22+
log.warning('There is already a config file. This will overwrite it!')
23+
await sleep(1000)
24+
}
1525

16-
// Ask user for assorted information
17-
const { product } = await prompts({
18-
type: 'select',
19-
name: 'product',
20-
message: 'Select a product to fork',
21-
choices: [
22-
{ title: 'Firefox stable', value: SupportedProducts.Firefox },
23-
{
24-
title: 'Firefox extended support (older)',
25-
value: SupportedProducts.FirefoxESR,
26-
},
26+
// Ask user for assorted information
27+
const { product } = await prompts({
28+
type: 'select',
29+
name: 'product',
30+
message: 'Select a product to fork',
31+
choices: [
32+
{ title: 'Firefox stable', value: SupportedProducts.Firefox },
33+
{
34+
title: 'Firefox extended support (older)',
35+
value: SupportedProducts.FirefoxESR,
36+
},
37+
{
38+
title: 'Firefox extended support (newer)',
39+
value: SupportedProducts.FirefoxESRNext,
40+
},
41+
{
42+
title: 'Firefox developer edition (Not recommended)',
43+
value: SupportedProducts.FirefoxDev,
44+
},
45+
{
46+
title: 'Firefox beta (Not recommended)',
47+
value: SupportedProducts.FirefoxBeta,
48+
},
49+
{
50+
title: 'Firefox Nightly (Not recommended)',
51+
value: SupportedProducts.FirefoxNightly,
52+
},
53+
],
54+
})
55+
56+
if (typeof product == 'undefined') return
57+
58+
const productVersion = await getLatestFF(product)
59+
60+
const { version, name, appId, vendor } = await prompts([
2761
{
28-
title: 'Firefox extended support (newer)',
29-
value: SupportedProducts.FirefoxESRNext,
62+
type: 'text',
63+
name: 'version',
64+
message: 'Enter the version of this product',
65+
initial: productVersion,
3066
},
3167
{
32-
title: 'Firefox developer edition (Not recommended)',
33-
value: SupportedProducts.FirefoxDev,
68+
type: 'text',
69+
name: 'name',
70+
message: 'Enter a product name',
71+
initial: 'Example browser',
3472
},
3573
{
36-
title: 'Firefox beta (Not recommended)',
37-
value: SupportedProducts.FirefoxBeta,
74+
type: 'text',
75+
name: 'vendor',
76+
message: 'Enter a vendor',
77+
initial: 'Example company',
3878
},
3979
{
40-
title: 'Firefox Nightly (Not recommended)',
41-
value: SupportedProducts.FirefoxNightly,
80+
type: 'text',
81+
name: 'appId',
82+
message: 'Enter an appid',
83+
initial: 'com.example.browser',
84+
// Horrible validation to make sure people don't chose something entirely wrong
85+
validate: (t: string) => t.includes('.'),
4286
},
43-
],
44-
})
45-
46-
if (typeof product == 'undefined') return
47-
48-
const productVersion = await getLatestFF(product)
49-
50-
const { version, name, appId, vendor } = await prompts([
51-
{
52-
type: 'text',
53-
name: 'version',
54-
message: 'Enter the version of this product',
55-
initial: productVersion,
56-
},
57-
{
58-
type: 'text',
59-
name: 'name',
60-
message: 'Enter a product name',
61-
initial: 'Example browser',
62-
},
63-
{
64-
type: 'text',
65-
name: 'vendor',
66-
message: 'Enter a vendor',
67-
initial: 'Example company',
68-
},
69-
{
70-
type: 'text',
71-
name: 'appId',
72-
message: 'Enter an appid',
73-
initial: 'com.example.browser',
74-
// Horrible validation to make sure people don't chose something entirely wrong
75-
validate: (t: string) => t.includes('.'),
76-
},
77-
])
78-
79-
const config: Config = {
80-
name,
81-
vendor,
82-
appId,
83-
version: { product, version, displayVersion: '1.0.0' },
87+
])
88+
89+
const config: Config = {
90+
name,
91+
vendor,
92+
appId,
93+
version: { product, version, displayVersion: '1.0.0' },
94+
}
95+
96+
await copyRequired()
97+
98+
writeFileSync(configPath, JSON.stringify(config, null, 2))
99+
} catch (e) {
100+
console.log(e)
101+
}
102+
}
103+
104+
// =============================================================================
105+
// Filesystem templating
106+
107+
const templateDir = join(__dirname, '../..', 'template')
108+
109+
async function copyRequired() {
110+
try {
111+
await Promise.all(
112+
(
113+
await walkDirectory(templateDir)
114+
)
115+
.filter((f) => !f.includes('.optional'))
116+
.map(async (file) => {
117+
const out = join(projectDir, file.replace(templateDir, ''))
118+
if (!existsSync(out)) {
119+
mkdirSync(dirname(out), { recursive: true })
120+
await copyFile(file, out)
121+
}
122+
})
123+
)
124+
} catch (e) {
125+
console.log(e)
126+
}
127+
}
128+
129+
// =============================================================================
130+
// Utility functions
131+
132+
const sleep = (time: number) => new Promise<void>((r) => setTimeout(r, time))
133+
134+
async function walkDirectory(dirName: string): Promise<string[]> {
135+
const output = []
136+
137+
if (!isAbsolute(dirName)) {
138+
log.askForReport()
139+
log.error('Please provide an absolute input to walkDirectory')
140+
}
141+
142+
try {
143+
const directoryContents = await readdir(dirName)
144+
145+
for (const file of directoryContents) {
146+
const fullPath = join(dirName, file)
147+
const fStat = await stat(fullPath)
148+
149+
if (fStat.isDirectory()) {
150+
for (const newFile of await walkDirectory(fullPath)) {
151+
output.push(newFile)
152+
}
153+
} else {
154+
output.push(fullPath)
155+
}
156+
}
157+
} catch (e) {
158+
log.askForReport()
159+
log.error(e)
84160
}
85161

86-
writeFileSync(configPath, JSON.stringify(config, null, 2))
162+
return output
87163
}

β€Žsrc/index.tsβ€Ž

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,23 @@
1+
import Log from './log'
2+
3+
// The logger must be initialized before the config generator, otherwise reference
4+
// errors occur
5+
export let log = new Log()
6+
17
import chalk from 'chalk'
28
import commander, { Command } from 'commander'
39
import { existsSync, readFileSync } from 'fs'
410
import { resolve } from 'path'
511
import { errorHandler, getConfig } from './utils'
612
import { commands } from './cmds'
713
import { ENGINE_DIR } from './constants'
8-
import Log from './log'
914
import { shaCheck } from './middleware/sha-check'
1015
import { updateCheck } from './middleware/update-check'
1116

1217
export const config = getConfig()
1318

1419
const program = new Command()
1520

16-
export let log = new Log()
17-
1821
program.storeOptionsAsProperties(false).passCommandToAction(false)
1922

2023
const { version: melon } = require('../package.json')

β€Žsrc/log.tsβ€Ž

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,15 @@ class Log {
4646
error(...args: any[]) {
4747
throw new Error(...args)
4848
}
49+
50+
askForReport() {
51+
console.info(
52+
'The following error is a bug. Please open an issue on the melon issue structure with a link to your repository and the output from this command.'
53+
)
54+
console.info(
55+
'The melon issue tracker is located at: https://github.com/dothq/melon/issues'
56+
)
57+
}
4958
}
5059

5160
export default Log

β€Žsrc/utils/config.tsβ€Ž

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,8 @@ import { join } from 'path'
77

88
import { log } from '..'
99

10-
const configDir = process.cwd()
11-
export const configPath = join(configDir, 'melon.json')
10+
export const projectDir = process.cwd()
11+
export const configPath = join(projectDir, 'melon.json')
1212

1313
export enum SupportedProducts {
1414
Firefox = 'firefox',
@@ -74,16 +74,15 @@ const defaultConfig: Config = {
7474
}
7575

7676
export function getConfig(): Config {
77-
const configExists = existsSync(configDir)
77+
const configExists = existsSync(configPath)
7878

7979
let fileContents = '{}'
8080
let fileParsed: Config
8181

8282
if (!configExists) {
8383
log.warning(
84-
`Config file not found at ${configDir}. It is recommended to create one by running |melon setup-project|`
84+
`Config file not found at ${configPath}. It is recommended to create one by running |melon setup-project|`
8585
)
86-
process.exit(1)
8786
} else {
8887
fileContents = readFileSync(configPath).toString()
8988
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
# Browser branding
2+
ac_add_options --enable-update-channel=release
3+
ac_add_options --with-branding=dot/branding
4+
ac_add_options --with-app-name=dot
5+
export MOZ_USER_DIR="${name}"
6+
export MOZ_APP_VENDOR="${vendor}"
7+
export MOZ_APP_BASENAME=Dot
8+
export MOZ_APP_PROFILE=dot
9+
export MOZ_APP_DISPLAYNAME="${name}"
10+
export MOZ_BRANDING_DIRECTORY=dot/branding
11+
export MOZ_OFFICIAL_BRANDING_DIRECTORY=dot/branding
12+
export MOZ_MACBUNDLE_ID=%{appId}
13+
export MOZ_DISTRIBUTION_ID=${appId}
14+
15+
# Uncomment if builds are too resource hungry
16+
# mk_add_options MOZ_MAKE_FLAGS="-j4"
17+
# ac_add_options --enable-linker=gold
18+
19+
# Misc
20+
export MOZ_STUB_INSTALLER=1
21+
export MOZ_INCLUDE_SOURCE_INFO=1
22+
export MOZ_SOURCE_REPO=https://github.com/dothq/browser-desktop
23+
export MOZ_SOURCE_CHANGESET=5893b1f8552ad0956b28ffd8105bf706bc9ee6fa
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
set -e
2+
3+
echo "Building Dot Browser for Linux"
4+
echo ""
5+
echo "This will take 10 to 60 minutes to complete."
6+
echo ""
7+
8+
echo "━━━━━━━━━ Setting up roles... ━━━━━━━━━"
9+
echo ""
10+
11+
sudo usermod -aG wheel worker
12+
sudo chown -R worker:worker /worker
13+
14+
echo ""
15+
echo "━━━━━━━━━ Setting up Rust... ━━━━━━━━━"
16+
echo ""
17+
18+
rustup install stable
19+
rustup default stable
20+
21+
echo ""
22+
echo "━━━━━━━━━ Installing dependencies... ━━━━━━━━━"
23+
echo ""
24+
25+
sudo pacman -Syu --noconfirm
26+
27+
echo ""
28+
echo "━━━━━━━━━ Bootstrapping... ━━━━━━━━━"
29+
echo ""
30+
31+
./mach bootstrap --application-choice browser --no-interactive
32+
33+
echo ""
34+
echo "━━━━━━━━━ Building... ━━━━━━━━━"
35+
echo ""
36+
37+
MOZCONFIG=/worker/build/mozconfig ./mach build
38+
39+
echo ""
40+
echo "━━━━━━━━━ Packaging... ━━━━━━━━━"
41+
echo ""
42+
43+
./mach package
44+
45+
echo ""
46+
echo "Dot Browser was successfully built!"
47+
echo "To take your build for a test drive, run: |melon run|"
48+
echo ""

0 commit comments

Comments
Β (0)