Skip to content

Commit

Permalink
feat: Add glob support (#2)
Browse files Browse the repository at this point in the history
  • Loading branch information
stefanbuck authored Sep 22, 2022
1 parent 3dbd1a9 commit 614612d
Show file tree
Hide file tree
Showing 5 changed files with 214 additions and 90 deletions.
46 changes: 40 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# octoherd-script-get-files

> An Octoherd script to download files from repositories
> The easiest way to download files from GitHub.
[![@latest](https://img.shields.io/npm/v/octoherd-script-get-files.svg)](https://www.npmjs.com/package/octoherd-script-get-files)
[![Build Status](https://github.com/stefanbuck/octoherd-script-get-files/workflows/Test/badge.svg)](https://github.com/stefanbuck/octoherd-script-get-files/actions?query=workflow%3ATest+branch%3Amain)
Expand All @@ -12,30 +12,64 @@ Minimal usage
```js
npx octoherd-script-get-files \
--source README.md \
--target ./out
--output ./out
```

Pass all options as CLI flags to avoid user prompts

```js
npx octoherd-script-get-files \
-T ghp_0123456789abcdefghjklmnopqrstuvwxyzA \
-R "stefanbuck/*" \
-R "octolinker/*" \
--source README.md \
--target ./out
--output ./out
```

## Options

| option | type | description |
| --------------------------------------------- | ---------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `--source` | string | **Required.** Path to the destination directory |
| `--target` | string | **Required.** File path to download. Note: Directories are not supported yet |
| `--source` | string | **Required.** File to download. This can also be a Glob see [example](#examples). |
| `--output` | string | **Required.** Specify a path to place the downloaded file or directory (instead of using the current working directory). Directories specified in the path will be created by this command. |
| `--ignore-archived` or `--no-ignore-archived` | boolean | Default `true`. Ignores archive repositories |
| `--octoherd-token`, `-T` | string | A personal access token ([create](https://github.com/settings/tokens/new?scopes=repo)). Script will create one if option is not set |
| `--octoherd-repos`, `-R` | array of strings | One or multiple space-separated repositories in the form of `repo-owner/repo-name`. `repo-owner/*` will find all repositories for one owner. `*` will find all repositories the user has access to. Will prompt for repositories if not set |
| `--octoherd-bypass-confirms` | boolean | Bypass prompts to confirm mutating requests |

## Examples

Download a single file

```js
npx octoherd-script-get-files -R octolinker/octolinker --source=README.md --output=./out
```

Download a single file by full path

```js
npx octoherd-script-get-files -R octolinker/octolinker --source=.github/PULL_REQUEST_TEMPLATE.md --output=./out
```

Download recursively all files with a certain file extension

```js
npx octoherd-script-get-files -R octolinker/octolinker --source='**/*.html' --output=./out
```

Download recursively all files from a specific folder

```js
npx octoherd-script-get-files -R octolinker/octolinker --source='.github/**/*' --output=./out
```

Download everything

```js
npx octoherd-script-get-files -R octolinker/octolinker --source='**/*' --output=./out
```

Don't know how to write Glob? Check out DigitalOcean's amazing [Glob testing tool](https://www.digitalocean.com/community/tools/glob).

## Contributing

See [CONTRIBUTING.md](CONTRIBUTING.md)
Expand Down
63 changes: 63 additions & 0 deletions helper.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
import os from 'os'
import fs from 'fs'
import path from 'path'
import minimatch from "minimatch"

export async function downloadFile(octokit, repository, target, source) {
const filepath = [repository.owner.login, repository.name, source].join('/');

return octokit.request(
`GET /repos/{owner}/{repo}/contents/${source}`,
{
owner: repository.owner.login,
repo: repository.name,
headers: {
Accept: "application/vnd.github.v3.raw"
}
}
).then((res) => {
octokit.log.info(`Download ${filepath}`);

// Expand the ~ character to a users home directory
const newTarget = target.replace("~", os.homedir)

const targetFile = path.join(newTarget, repository.owner.login, repository.name, source);
const targetPath = path.join(newTarget, repository.owner.login, repository.name, path.dirname(source));

if (!fs.existsSync(targetPath)) {
fs.mkdirSync(targetPath, { recursive: true });
}

fs.writeFileSync(targetFile, res.data)
}).catch(error => {
if (error.status === 404) {
octokit.log.warn(`File ${filepath} not found`);
return false;
}

throw error;
})
}

export async function getListOfFilesToDownload(octokit, repository, source) {
const res = await octokit.request(
`GET /repos/{owner}/{repo}/git/trees/HEAD?recursive=true`,
{
owner: repository.owner.login,
repo: repository.name,
headers: {
Accept: "application/vnd.github.v3.raw"
}
}).catch(error => {
if (error.status === 409) {
octokit.log.warn(`Git Repository is empty`);
return { data: { tree: [] } };
}

throw error;
})

const tree = res?.data?.tree?.filter(item => item.type === 'blob').map(item => item.path);

return tree.filter(item => minimatch(item, source))
}
138 changes: 89 additions & 49 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 3 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,9 @@
"author": "Stefan Buck (stefanbuck.com)",
"license": "ISC",
"dependencies": {
"@octoherd/cli": "^3.4.11"
"@octoherd/cli": "^3.4.11",
"is-glob": "^4.0.3",
"minimatch": "^5.1.0"
},
"release": {
"branches": [
Expand Down
Loading

0 comments on commit 614612d

Please sign in to comment.