Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement 'copy' plugin #128 #367

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
88 changes: 87 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ Dotbot makes installing your dotfiles as easy as `git clone $url && cd dotfiles
- [Rationale](#rationale)
- [Getting Started](#getting-started)
- [Configuration](#configuration)
- [Directives](#directives) ([Link](#link), [Create](#create), [Shell](#shell), [Clean](#clean), [Defaults](#defaults))
- [Directives](#directives) ([Link](#link), [Create](#create), [Copy](#copy), [Shell](#shell), [Clean](#clean), [Defaults](#defaults))
- [Plugins](#plugins)
- [Command-line Arguments](#command-line-arguments)
- [Wiki][wiki]
Expand Down Expand Up @@ -278,6 +278,92 @@ Implicit sources:
relink: true
```

### Copy

Copy commands specify how files should be copied. By default, files will be copied if the destination file does not exist however this behavior can be changed to overwrite existing files or copy if the source and destination contents differ. Like Link, environment variables in paths are automatically expanded.

#### Format
Copy commands are specified as a dictionary that maps targets to source locations. Source locations are specified relative to the base directory (that is specified when running the installer). If the source is a directory, that entire directory hierarchy will be copied.

Copy commands support an optional extended configuration. In this type of configuration, instead of specifying source locations directly, targets are mapped to extended configuration dictionaries.


| Parameter | Explanation |
| --- | --- |
| `path` | The source file for the copy, the same as in the shortcut syntax (default: null, automatic (see below)) |
| `create` | When true, create parent directories to the destination file as needed. (default: false) |
| `overwrite` | Overwrites the destination file if one exists (default: false) |
| `if` | Execute this in your `$SHELL` and only copy if it is successful. |
| `ignore-missing` | Do not fail if the source is missing (default: false) |
| `exclude` | Array of glob patterns to remove from list of source files top copy. Uses same syntax as `path`. (default: empty, keep all matches) |
| `check-content` | Compare the contents of the source and destination files, copy if different (default: false) |
| `dryrun` | Don't copy any files, output what would have been copied. Useful for debugging configuration (default false) |
| `mode` | Set the mode on the destination file (default: copy metadata from source) |
| `dir-mode` | Set the mode on any directories created (default: 0755) |
| `prefix` | Prepend prefix prefix to the path at the root of the source tree when creating the destination path. See the example below for more details (only enabled if glob characters are in use). (default: '') |
| `backup` | Make a backup of the destination file, if it exists. `backup` can be a bool or a string. If set to `false`, Copy will not create a backup of the destination. If set to `true`, Copy will use the destination path with the suffix `.BAK` as the backup path name. If set to a string, Copy will add that string to the destination path to create a backup path name. (default: None) |

Unlike Link, Copy will apply globbing if the source path contains any of the shell wildcard characters. Wildcard expansion for the `path` and `exclude` parameters are identical to Link.

#### Example
```yaml
- copy:
~/.project: dot.project
~/.login: dot.login
~/.cshrc: dot.cshrc
~/.emacs.d:
path: dot.emacs.d
exclude: [ .saves*, *~ ]
~/bin:
mode: 0750
overwrite: true
```

This configuration copies a directory tree `source_dir` to `~/dest_dir`, excluding any files that match the wildcard pattern. It also creates destination directories as needed, forcing the mode to 0700:

```yaml
- copy:
~/dest_dir:
path: source_dir
exclude: [ *~, do-not-copy* ]
dir-mode: 0700
```

Copy and Link can be used together. The following example copies a tcsh configuration file to `~/.cshrc` and creates a link from an alternate default file name `~/.tcshrc` to the copied file.

```yaml
- copy:
~/.cshrc: dot.cshrc
- link:
~/.tcshrc: .cshrc
```

This example shows how `prefix` can be used. For the source directory:
```
dot/profile
dot/config/gnome/...
dot/config/nano/...
forward
```

the config:

```yaml
- copy:
~/:
path: dot/**
prefix: '.'
create: true
```

Will create:
```
~/.profile
~/.config/gnome/...
~/.config/nano/...
~/.forward
```

### Create

Create commands specify empty directories to be created. This can be useful
Expand Down
4 changes: 2 additions & 2 deletions dotbot/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
from .config import ConfigReader, ReadingError
from .dispatcher import Dispatcher, DispatchError
from .messenger import Level, Messenger
from .plugins import Clean, Create, Link, Shell
from .plugins import Clean, Copy, Create, Link, Shell
from .util import module


Expand Down Expand Up @@ -121,7 +121,7 @@ def main():
plugins = []
plugin_directories = list(options.plugin_dirs)
if not options.disable_built_in_plugins:
plugins.extend([Clean, Create, Link, Shell])
plugins.extend([Clean, Copy, Create, Link, Shell])
plugin_paths = []
for directory in plugin_directories:
for plugin_path in glob.glob(os.path.join(directory, "*.py")):
Expand Down
1 change: 1 addition & 0 deletions dotbot/plugins/__init__.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
from .clean import Clean
from .copy import Copy
from .create import Create
from .link import Link
from .shell import Shell
Loading