From 9dc6f9d2144cf60a7759f921378fd025b699056a Mon Sep 17 00:00:00 2001 From: garrettmills Date: Thu, 5 Mar 2020 11:48:38 -0600 Subject: [PATCH] Add git.clone and git.checkout states --- app/classes/git/Repository.js | 14 ++++++++ app/classes/state/git/CheckoutState.js | 45 ++++++++++++++++++++++++++ app/classes/state/git/CloneState.js | 33 +++++++++++++++++++ app/classes/state/os/CommandState.js | 2 ++ app/services/states.service.js | 4 ++- 5 files changed, 97 insertions(+), 1 deletion(-) create mode 100644 app/classes/state/git/CheckoutState.js create mode 100644 app/classes/state/git/CloneState.js diff --git a/app/classes/git/Repository.js b/app/classes/git/Repository.js index d7069a1..cd1795f 100644 --- a/app/classes/git/Repository.js +++ b/app/classes/git/Repository.js @@ -62,6 +62,20 @@ class Repository extends Injectable { await this._git_cmd(`checkout "${ref}"`) } + async current_branch() { + const cd_cmd = await this._host.get_directory_change_command(this._path) + const cmd = `${cd_cmd} && git symbolic-ref HEAD` + const full_ref = await this._host.run_line_result(cmd) + return full_ref.replace('refs/heads/', '') + } + + async current_ref() { + const cd_cmd = await this._host.get_directory_change_command(this._path) + const cmd = `${cd_cmd} && git show-ref HEAD` + const ref = await this._host.run_line_result(cmd) + return ref.split(' ')[0] + } + async stash() { await this._git_cmd(`stash`) } diff --git a/app/classes/state/git/CheckoutState.js b/app/classes/state/git/CheckoutState.js new file mode 100644 index 0000000..7f3086d --- /dev/null +++ b/app/classes/state/git/CheckoutState.js @@ -0,0 +1,45 @@ +const State = require('../State') +const Repository = require('../../git/Repository') + +class CheckoutState extends State { + static get services() { + return [...super.services, 'output'] + } + + async apply() { + if ( !(await this.check()) ) { + const repo = await this._repo() + await repo.checkout(this._config.target) + } + } + + async check() { + const repo = await this._repo() + const target = await this._config.target + try { + if ( (await repo.current_branch()) === target ) return true + if ( (await repo.current_ref()) === target ) return true + } catch (e) {} + return false + } + + async reverse() { + if ( this._config.revert_to ) { + if ( await this.check() ) { + const repo = await this._repo() + await repo.checkout(this._config.revert_to) + } + } else { + this.output.warn('Checkout state does not currently support automatic reversal. Specify the revert_to config key to enable.') + } + } + + async _repo() { + const path = await this._host.get_path(this._config.path) + if ( !path.is_valid() ) await path.touch(true) + return new Repository(path) + } + +} + +module.exports = exports = CheckoutState diff --git a/app/classes/state/git/CloneState.js b/app/classes/state/git/CloneState.js new file mode 100644 index 0000000..8bfcdeb --- /dev/null +++ b/app/classes/state/git/CloneState.js @@ -0,0 +1,33 @@ +const State = require('../State') +const Repository = require('../../git/Repository') + +class CloneState extends State { + + async apply() { + if ( !(await this.check()) ) { + const repo = await this._repo() + await repo.clone(this._config.source) + } + } + + async check() { + const repo = await this._repo() + return repo.is_repo() + } + + async reverse() { + if ( await this.check() ) { + const path = await this._host.get_path(this._config.path) + await path.unlink() + } + } + + async _repo() { + const path = await this._host.get_path(this._config.path) + if ( !path.is_valid() ) await path.touch(true) + return new Repository(path) + } + +} + +module.exports = exports = CloneState diff --git a/app/classes/state/os/CommandState.js b/app/classes/state/os/CommandState.js index 47bbf4d..be88ebc 100644 --- a/app/classes/state/os/CommandState.js +++ b/app/classes/state/os/CommandState.js @@ -18,6 +18,8 @@ class CommandState extends State { if ( this._config.reverse ) { const cmd = `${this._config.reverse}` await this._host.run(cmd) + } else { + this.output.warn(`No reversal command specified for Command State. Nothing was changed. (Host: ${this._host.name})`) } } diff --git a/app/services/states.service.js b/app/services/states.service.js index e9b7717..86500a7 100644 --- a/app/services/states.service.js +++ b/app/services/states.service.js @@ -14,7 +14,6 @@ class StatesService extends Service { // TODO apache and nginx states - virtual host, reverse proxy // TODO package repository states - import keys, install repository // TODO service manager states - service enabled, service installed, stopped - // TODO git states - clone repo, ref checked out // TODO package states - uninstalled 'fs.file': require('../classes/state/fs/FileState'), @@ -24,6 +23,9 @@ class StatesService extends Service { 'fs.permission': require('../classes/state/fs/PermissionState'), 'fs.ownership': require('../classes/state/fs/OwnerState'), + 'git.clone': require('../classes/state/git/CloneState'), + 'git.checkout': require('../classes/state/git/CheckoutState'), + 'os.cmd': require('../classes/state/os/CommandState'), 'package.present': require('../classes/state/os/PackageState'),