Skip to content

Commit 86075e9

Browse files
authored
fix: use shared config fns (#12)
1 parent 8448b4a commit 86075e9

File tree

17 files changed

+125
-72
lines changed

17 files changed

+125
-72
lines changed

README.md

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,8 @@ $ ghq
2525
npx ghq-node
2626
```
2727

28-
```console
29-
ghq/1.0.1
28+
```
29+
ghq/0.0.0
3030
3131
Usage:
3232
$ ghq <command> [options]
@@ -35,12 +35,14 @@ Commands:
3535
get [repo] Clone/sync with a remote repository
3636
create [repo] Create a new repository
3737
list [query] List local repositories
38-
root Show repositories' root
38+
config Manage the ghq configuration file
39+
root Alias to `ghq config --get.root`
3940
4041
For more info, run any command with the `--help` flag:
4142
$ ghq get --help
4243
$ ghq create --help
4344
$ ghq list --help
45+
$ ghq config --help
4446
$ ghq root --help
4547
4648
Options:

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
"prettier": "2.5.1",
3535
"tsup": "6.0.1",
3636
"typescript": "4.5.4",
37+
"url-join": "^5.0.0",
3738
"vitest": "0.12.6"
3839
}
3940
}

pnpm-lock.yaml

Lines changed: 7 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/commands/config.ts

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,9 @@
1-
import { printConfig, writeUserConfig } from '../config'
1+
import {
2+
existsUserConfig,
3+
printConfig,
4+
writeUserConfig,
5+
ghqConfigFileName,
6+
} from '../config'
27
import { Config, OptionalConfig, PluginApi } from '../types'
38

49
export const config: PluginApi = {
@@ -11,6 +16,13 @@ export const config: PluginApi = {
1116
.example('ghq config --get.root')
1217
.option('-l, --list', 'List all')
1318
.action(async (options) => {
19+
if (!(await existsUserConfig())) {
20+
console.info(
21+
'`' + ghqConfigFileName + '` file not found!',
22+
'Fallback to default configs.\n',
23+
)
24+
}
25+
1426
if (options.list) {
1527
await printConfig()
1628
return

src/commands/get.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ export const get: PluginApi = {
66
extend(api) {
77
api.cli
88
.command('get [repo]', 'Clone/sync with a remote repository')
9+
.alias('clone')
910
.example('ghq get 2nthony/ghq')
1011
.example('ghq get github.com/2nthony/ghq')
1112
.example('ghq get https://github.com/2nthony/ghq')

src/commands/list.ts

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,29 @@
11
import { PluginApi } from '../types'
22
import path from 'path'
3-
import { rootPath } from '../shared'
43
import { analyzeUrl } from '../shared/url'
54
import { collectDirs } from '../fs'
65
import { PathLike } from 'fs'
6+
import { resolveConfig } from '../config'
77

88
export const list: PluginApi = {
99
extend(api) {
1010
api.cli
1111
.command('list [query]', 'List local repositories')
12+
.alias('ls')
1213
.option('-p, --full-path', 'Print full path', {
1314
default: false,
1415
})
1516
.action(async (query, { fullPath }) => {
17+
const { root } = await resolveConfig()
18+
1619
/**
1720
* deep `4` means:
1821
* 1 ~/ghq
1922
* 2 github.com
2023
* 3 user
2124
* 4 repo
2225
*/
23-
let entries = await collectDirs(rootPath, 4)
26+
let entries = await collectDirs(root, 4)
2427

2528
if (query) {
2629
entries = entries.filter((entry) => {
@@ -39,7 +42,7 @@ export const list: PluginApi = {
3942
}
4043

4144
function relativeRootPath(entryPath: PathLike) {
42-
return path.relative(rootPath, entryPath.toString())
45+
return path.relative(root, entryPath.toString())
4346
}
4447

4548
function print(entry: PathLike) {

src/commands/root.ts

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,11 @@
1-
import { rootPath } from '../shared'
1+
import { resolveConfig } from '../config'
22
import { PluginApi } from '../types'
33

44
export const root: PluginApi = {
55
extend(api) {
6-
api.cli
7-
.command('root', "Show repositories' root (un-implemented)")
8-
.action(() => {
9-
console.info(rootPath)
10-
})
6+
api.cli.command('root', 'Alias to `ghq config --get.root`').action(() => {
7+
const { root } = resolveConfig()
8+
console.info(root)
9+
})
1110
},
1211
}

src/config.ts

Lines changed: 10 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,10 @@
11
import { Config, OptionalConfig } from './types'
22
import { homedir } from 'os'
3-
import path from 'path'
4-
import { read, writeJson } from './fs'
5-
import { expandTildePath } from './path'
3+
import { exists, read, writeJson } from './fs'
4+
import { expandTildePath, join } from './path'
65

7-
const ghqConfigFileName = '.ghqrc'
8-
const userConfigFilePath = path.join(homedir(), ghqConfigFileName)
6+
export const ghqConfigFileName = '.ghqrc'
7+
export const userConfigFilePath = join(homedir(), ghqConfigFileName)
98

109
const defaultConfig: Config = {
1110
root: '~/ghq',
@@ -27,19 +26,14 @@ export async function readConfig() {
2726
}
2827
}
2928

30-
export async function readUserConfig(): Promise<OptionalConfig> {
31-
const rawConfig = await read(userConfigFilePath)
32-
33-
if (!rawConfig) {
34-
console.info(
35-
'`' + ghqConfigFileName + '` file not found!',
36-
'Fallback to default configs.\n',
37-
)
38-
return {}
39-
}
29+
export async function existsUserConfig() {
30+
return await exists(userConfigFilePath)
31+
}
4032

33+
export async function readUserConfig(): Promise<OptionalConfig> {
4134
try {
42-
return JSON.parse(rawConfig)
35+
const rawConfig = await read(userConfigFilePath)
36+
return rawConfig ? JSON.parse(rawConfig) : {}
4337
} catch {
4438
return {}
4539
}

src/fs.ts

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,24 @@
11
import { PathLike } from 'fs'
22
import fs from 'fs/promises'
3-
import path from 'path'
3+
import { join } from './path'
44
import { Config } from './types'
55

66
export async function makeDir(dirPath: PathLike) {
77
return await fs.mkdir(dirPath, { recursive: true })
88
}
99

10-
export async function exists(dirPath: PathLike) {
11-
return await fs
12-
.access(dirPath)
13-
.then(() => true)
14-
.catch(() => false)
10+
export async function exists(targetPath: PathLike) {
11+
try {
12+
await fs.access(targetPath)
13+
return true
14+
} catch {
15+
return false
16+
}
1517
}
1618

17-
export async function read(targetPath: PathLike) {
19+
export async function read(filePath: PathLike) {
1820
try {
19-
return await fs.readFile(targetPath, 'utf8')
21+
return await fs.readFile(filePath, 'utf8')
2022
} catch {
2123
return ''
2224
}
@@ -37,6 +39,10 @@ export async function collectDirs(dirPath: PathLike, deep = 1) {
3739
await read(dirPath)
3840

3941
async function read(currentDirPath: typeof dirPath) {
42+
if (!(await exists(currentDirPath))) {
43+
return
44+
}
45+
4046
currentDeep += 1
4147

4248
if (currentDeep === deep) {
@@ -51,7 +57,7 @@ export async function collectDirs(dirPath: PathLike, deep = 1) {
5157
for (let index = 0; index < dirDirents.length; index++) {
5258
const dirent = dirDirents[index]
5359

54-
await read(path.join(currentDirPath.toString(), dirent.name))
60+
await read(join(currentDirPath.toString(), dirent.name))
5561

5662
/**
5763
* if this dirent is the last directory

src/git.ts

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,13 @@
11
import { execSync, spawn } from 'child_process'
2-
import path from 'path'
3-
import { rootPath } from './shared'
2+
import { resolveConfig } from './config'
43
import { exists, makeDir } from './fs'
4+
import { join } from './path'
55
import { analyzeUrl, composeUrl } from './shared/url'
66
import { Repo } from './types'
77

8-
export function repoDest(repo: Repo) {
9-
return path.join(rootPath, repo.host, repo.user, repo.name)
8+
export async function repoDest(repo: Repo) {
9+
const { root } = await resolveConfig()
10+
return join(root, repo.host, repo.user, repo.name)
1011
}
1112

1213
function git(cmd: string, dest: string, ...args: string[]) {
@@ -19,7 +20,7 @@ export const username = getUsername()
1920

2021
export async function clone(repoUrl: string, ...args: string[]) {
2122
const repo = analyzeUrl(repoUrl)
22-
const dest = repoDest(repo)
23+
const dest = await repoDest(repo)
2324

2425
if (!(await exists(dest))) {
2526
await makeDir(dest)
@@ -30,7 +31,7 @@ export async function clone(repoUrl: string, ...args: string[]) {
3031

3132
export async function init(repoUrl: string, ...args: string[]) {
3233
const repo = analyzeUrl(repoUrl)
33-
const dest = repoDest(repo)
34+
const dest = await repoDest(repo)
3435

3536
if (!(await exists(dest))) {
3637
await makeDir(dest)

0 commit comments

Comments
 (0)