Describe the feature
I maintain a set of static files like dotfiles or other configs (.vscode/*, .editorconfig, eslint.config.ts, LICENSE, etc.) with mostly the same contents across dozens of repos. When I update any of those, I usually need to update most of them. Instead of doing this manually, I want to update one central template repository and pull changes to the others. I don't want to sync the entire repo but be able to select specific files to sync so I can easily deviate from the template repo.
Tools like GitPick already let you fetch arbitrary blobs from a Git provider’s raw endpoint. It would be great if giget could:
- Let me specify a list of files to pull.
- Integrate into npm scripts or a
giget.config.(cjs|ts) (c12-style) so I can store my sync-list in source.
- Honor a conflict strategy (
skip | overwrite | merge in the future) when a target file already exists.
Proposal
New CLI flag & API
I'm not sure yet if I should call the flag --files or --include. The latter has the advantage that an --exclude flag could be added as a filter, so I could --include .vscode --exclude .vscode/settings.json for example. But I think the best solution would be to use the .gitignore-Syntax to exclude files with an exclamation mark.
# sync only license and VSCode settings folder
giget gh:unjs/giget output-dir --strategy overwrite --files README.md --files .github
import { downloadTemplate } from 'giget'
await downloadTemplate('unjs/dotfiles', {
dir: 'output-dir',
files: [
'README.md',
'.github'
],
strategy: 'overwrite', // skip | overwrite | merge
})
--files <paths…> (repeatable): list of file or folder paths to fetch (I guess this is how you use arrays with citty? Atleast it works).
strategy (skip | overwrite | merge): what to do when a target already exists.
- raw-HTTP loop: for each file in
files, attempt template.raw(path) → fetch → write.
- partial-tarball extract: if any path is a folder (or raw fetch throws), download the tarball and filter by those paths.
Config-file support (c12 integration)
// giget.config.ts
export default {
dir: '.',
files: [
'.editorconfig',
'eslint.config.ts',
'.vscode/**/*',
],
strategy: 'overwrite',
}
Then in your package.json:
import { resolve } from 'node:path'
import type { FileConfig, IncludeEntry, Source } from './src/config'
const config: FileConfig = {
branch: 'main',
strategy: 'overwrite',
cache: false,
sources: [
{
repo: 'github:unjs/giget',
branch: 'develop', // can be overwritten for each source
files: [
// simple string → { src: 'path', dest: 'path' }
'.editorconfig',
'LICENSE',
// object form to rename or relocate
{ src: '.vscode/settings.json', dest: resolve(process.cwd(), '.vscode/settings.json'), strategy: 'skip' },
// sync an entire folder
'.vscode/',
],
},
{
// pick single file from a bitbucket repo:
repo: 'bitbucket:acme/common-config',
include: ['eslint.config.ts'],
} as Source,
],
}
Implementation Notes
I have already implemented a working prototype. The following is summarized by Copilot based on my code. Maybe this helps with discussing early before I can submit a PR, but things might change:
--files flag
- In cli.ts, define a multi-value
files arg, normalize to string[].
- Raw download pass
- In
downloadTemplate, if options.files is set and no folder-only paths remain, loop over each path:
for (const p of options.files) {
const url = template.raw(p)
const res = await sendFetch(url)
await writeFile(destDir/p, await res.arrayBuffer())
}
return early
- Partial-tarball extraction
- If any entry ends with
/ (folder), or if any raw fetch fails, download the .tar.gz, then:
await tarExtract({
file: tarPath,
cwd: destDir,
strip: 1,
filter: entry => {
const rel = entry.path.split('/').slice(1).join('/')
return files.some(f =>
rel === f || rel.startsWith(f + '/')
)
}
})
- Fallback & full extract
- If
--files is omitted, or after partial extract, proceed with the existing full-tarball logic + installDependencies.
Is this functionality wanted in giget? If so, I would be happy to submit a PR. Please let me know if you have better ideas to address my use case or if you would change some implementation details.
Additional information
Describe the feature
I maintain a set of static files like dotfiles or other configs (
.vscode/*,.editorconfig,eslint.config.ts,LICENSE, etc.) with mostly the same contents across dozens of repos. When I update any of those, I usually need to update most of them. Instead of doing this manually, I want to update one central template repository and pull changes to the others. I don't want to sync the entire repo but be able to select specific files to sync so I can easily deviate from the template repo.Tools like GitPick already let you fetch arbitrary blobs from a Git provider’s raw endpoint. It would be great if giget could:
giget.config.(cjs|ts)(c12-style) so I can store my sync-list in source.skip|overwrite|mergein the future) when a target file already exists.Proposal
New CLI flag & API
I'm not sure yet if I should call the flag
--filesor--include. The latter has the advantage that an--excludeflag could be added as a filter, so I could--include .vscode --exclude .vscode/settings.jsonfor example. But I think the best solution would be to use the .gitignore-Syntax to exclude files with an exclamation mark.# sync only license and VSCode settings folder giget gh:unjs/giget output-dir --strategy overwrite --files README.md --files .github--files <paths…>(repeatable): list of file or folder paths to fetch (I guess this is how you use arrays with citty? Atleast it works).strategy(skip|overwrite|merge): what to do when a target already exists.files, attempttemplate.raw(path) → fetch → write.Config-file support (c12 integration)
Then in your package.json:
Implementation Notes
I have already implemented a working prototype. The following is summarized by Copilot based on my code. Maybe this helps with discussing early before I can submit a PR, but things might change:
--filesflagfilesarg, normalize tostring[].downloadTemplate, ifoptions.filesis set and no folder-only paths remain, loop over each path:/(folder), or if any raw fetch fails, download the.tar.gz, then:--filesis omitted, or after partial extract, proceed with the existing full-tarball logic +installDependencies.Is this functionality wanted in giget? If so, I would be happy to submit a PR. Please let me know if you have better ideas to address my use case or if you would change some implementation details.
Additional information