Commit 5afd3b9d authored by Aral Balkan's avatar Aral Balkan

Improve sync syntax (closes #13)

parent b846f39d
......@@ -8,6 +8,12 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
Nothing yet.
## [10.0.0] - 2019-05-12
### Changed
- By default, sync contents of the folder, regardless of whether it is specified in the arguments with or without a trailing slash, and only sync the folder and its contents if the new --sync-folder-and-contents flag is specified (breaking change).
## [9.3.0] - 2019-05-12
### Added
......
......@@ -60,13 +60,13 @@ This will create and serve the following proxies:
Part of local development involves deploying your changes to a live server at some point. You can use Indie Web Server to handle this for you in real-time:
```shell
$ web-server sync my-demo/ my-demo.site
$ web-server sync my-demo my-demo.site
```
The above command will start a local development server at _https://localhost_. Additionally, it will watch the folder _my-demo_ for changes and sync any changes via rsync over ssh to _my-demo.site_. Without any customisations, the sync command assumes that your account on your remote server has the same name as your account on your local machine and that the folder you are watching (_my-demo_, in the example above) is located at _/home/your-account/my-demo_. You can change these defaults using optional arguments.
The above command will start a local development server at _https://localhost_. Additionally, it will watch the folder _my-demo_ for changes and sync any changes to its contents via rsync over ssh to _my-demo.site_. Without any customisations, the sync command assumes that your account on your remote server has the same name as your account on your local machine and that the folder you are watching (_my-demo_, in the example above) is located at _/home/your-account/my-demo_. Also, by default, the contents of the folder will be synced, not the folder itself. You can change these defaults using optional arguments.
```shell
$ web-server sync my-folder/ --host=my-demo.site --account=a-different-account --folder=not-my-folder
$ web-server sync my-folder --host=my-demo.site --account=a-different-account --folder=not-my-folder
```
e.g., The above command will watch the the contents of the _my-folder_ directory and sync it to _a-different-account@my-demo.site:/home/a-different-account/not-my-folder_.
......@@ -74,14 +74,20 @@ e.g., The above command will watch the the contents of the _my-folder_ directory
You can also customise the destination folder completely but supplying a custom remote connection string using the `--to` option:
```shell
$ web-server sync my-folder/ --to=some-account@my-demo.site:/var/www
$ web-server sync my-folder --to=some-account@my-demo.site:/var/www
```
Like the other commands, if you do not specify a folder, the current folder will be used by default.
__Important:__ The trailing slash is important. It means “sync the contents of this folder but not the folder itself”. If you leave out the trailing slash, it means “sync the contents of this folder and the folder itself”. The latter will result in a folder of the same name as your local folder being created in your destination folder on the remote server. Indie Web Server inherits this functionality from the rsync command itself and keeps it for consistency.
If you want to sync not the folder’s contents but the folder itself, use the `--sync-folder-and-contents` flag. e.g.,
__Note:__ If you want to carry out a one-time sync and not run the server afterwards, use the `--exit-on-sync` flag. e.g.,
```shell
$ web-server sync my-local-folder/ my.site --account=me --folder=my-remote-folder
```
The above command will result in the following directory structure on the remote server: _/home/me/my-remote-folder/my-local-folder_
If you want to carry out a one-time sync and not continue to run the web server afterwards, use the `--exit-on-sync` flag. e.g.,
```shell
$ web-server sync my-folder my-demo.site --exit-on-sync
......@@ -225,6 +231,8 @@ If `command` is omitted, behaviour defaults to `local`.
* `--account`: The ssh account to use on remote server (defaults to same as on current session).
* `--folder`: The subfolder of home folder to sync to on remote machine (defaults to name of served folder).
* `--proxy`: Proxy the specified host and port instead of starting a regular local server.
* `--exit-on-sync`: Exit once the first sync has occurred. Useful in deployment scripts.
* `--sync-folder-and-contents`: Sync folder and contents (default is to sync the folder’s contents only).
All command-line arguments are optional. By default, Indie Web Server will serve your current working folder over port 443 with locally-trusted certificates.
......
......@@ -44,6 +44,7 @@ function help () {
const optionProxy = option('proxy')
const optionSync = option('sync')
const optionExitOnSync = option('exit-on-sync')
const optionSyncFolderAndContents = option('sync-folder-and-contents')
const prompt = clr('', 'blue')
......@@ -87,11 +88,12 @@ function help () {
For the ${commandSync} command:
${optionHost}\tThe remote host to sync to (e.g., my-demo.site).
${optionAccount}\tThe ssh account to use on remote server (defaults to same as on current session).
${optionFolder}\tThe subfolder of home folder to sync to on remote machine (defaults to name of served folder).
${optionProxy}\tProxy the specified host and port instead of starting a regular local server.
${optionExitOnSync}\tExit once the first sync has occurred. Useful in deployment scripts.
${optionHost}\t\t\tThe remote host to sync to (e.g., my-demo.site).
${optionAccount}\t\t\tThe ssh account to use on remote server (defaults to same as on current session).
${optionFolder}\t\t\tThe subfolder of home folder to sync to on remote machine (defaults to name of served folder).
${optionProxy}\t\t\tProxy the specified host and port instead of starting a regular local server.
${optionExitOnSync}\t\tExit once the first sync has occurred. Useful in deployment scripts.
${optionSyncFolderAndContents}\tSync local folder and contents (default is to sync the folder’s contents only).
${heading('Examples:')}
......
......@@ -262,9 +262,6 @@ class CommandLineInterface {
return typeof command.namedArguments[namedArgument] === 'string'
}
''
// Sync on exit flag.
syncOptions.syncExitOnSync = command.namedArguments['exit-on-sync'] === true
// Check for conflicts between positional arguments and named arguments
// and fail if there are any.
if (namedArgumentExists('to')) {
......@@ -281,8 +278,8 @@ class CommandLineInterface {
this.syntaxError(`could not parse rsync connection string in ${clr('--to', 'yellow')} option (${clr(command.namedArguments.to, 'cyan')}). It should be in the form ${clr('account@host:/path/to/folder', 'cyan')}`)
}
// Helper: redundant but useful so we don’t have to parse the remote connection string again.
syncOptions.syncRemoteHost = remoteConnectionStringSyntaxMatch[2]
// Helper: redundant but useful so we don’t have to parse the remote connection string again.
syncOptions.syncRemoteHost = remoteConnectionStringSyntaxMatch[2]
// No conflicts or syntax issues: set the remote connection string to the one provided.
syncOptions.syncRemoteConnectionString = command.namedArguments.to
......@@ -335,6 +332,26 @@ class CommandLineInterface {
//
// Add any remaining sync options that have been provided.
//
// Handle the sync-folder-and-contents flag or its lack
if (command.namedArguments['sync-folder-and-contents'] === true) {
// We should sync both the folder itself and its contents. We signal this to rsync
// by ensuring that the name of the folder *does not* end in a trailing slash.
if (syncOptions.syncLocalFolder.endsWith(path.sep)) {
syncOptions.syncLocalFolder = syncOptions.syncLocalFolder.substr(0, syncOptions.syncLocalFolder.length - 1)
}
} else {
// Default: we sync only the contents of the local folder, not the folder itself. To
// ======== specify this to rsync, we ensure that the local folder path ends with a slash.
if (!syncOptions.syncLocalFolder.endsWith(path.sep)) {
syncOptions.syncLocalFolder = `${syncOptions.syncLocalFolder}${path.sep}`
}
}
// Sync on exit flag.
syncOptions.syncExitOnSync = command.namedArguments['exit-on-sync'] === true
// Proxy.
if (namedArgumentExists('proxy')) {
syncOptions.syncStartProxyServer = true
const proxyOptions = this.proxyUrls(command.namedArguments.proxy)
......
{
"name": "@ind.ie/web-server",
"version": "9.3.0",
"version": "10.0.0",
"description": "A secure and seamless Small Tech personal web server.",
"main": "index.js",
"bin": "bin/web-server.js",
......
......@@ -361,7 +361,15 @@ test('[CLI] proxyOptions()', t => {
test('[CLI] syncOptions()', t => {
// This method is thoroughly tested via the sync command tests. These are just a few method-specific tests.
t.plan(6)
t.plan(9)
// A folder passed without a trailing slash should have one added by default so that
// rsync syncs the contents of the folder only, not the folder itself also.
t.strictEquals(cli.syncOptions(cli.command({_:['sync', 'test/site', 'my.site']})).syncLocalFolder, 'test/site/', 'a trailing slash should be added to the local folder if missing for default sync')
// If we specify the --sync-folder-and-contents option, then the folder should not have a trailing slash, even
// if the person has provided one.
t.strictEquals(cli.syncOptions(cli.command({_:['sync', 'test/site/', 'my.site'], 'sync-folder-and-contents': true})).syncLocalFolder, 'test/site', 'a trailing slash should be removed from the local folder if it exists when --sync-folder-and-contents is true')
// Non-sync command should return sync options object will all nulls.
const syncOptions = cli.syncOptions(cli.command({_:[]}))
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment