Ready to install.

This commit is contained in:
tmerritt committed 2021-07-24 14:35:10 -04:00
1 parent c6387a96f2
commit 8134556e58
20 files changed
+713 -88

No files matched your search

+129
View File
@@ -0,0 +1,129 @@
# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
*$py.class
# C extensions
*.so
# Distribution / packaging
.Python
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
wheels/
pip-wheel-metadata/
share/python-wheels/
*.egg-info/
.installed.cfg
*.egg
MANIFEST
# PyInstaller
# Usually these files are written by a python script from a template
# before PyInstaller builds the exe, so as to inject date/other infos into it.
*.manifest
*.spec
# Installer logs
pip-log.txt
pip-delete-this-directory.txt
# Unit test / coverage reports
htmlcov/
.tox/
.nox/
.coverage
.coverage.*
.cache
nosetests.xml
coverage.xml
*.cover
*.py,cover
.hypothesis/
.pytest_cache/
# Translations
*.mo
*.pot
# Django stuff:
*.log
local_settings.py
db.sqlite3
db.sqlite3-journal
# Flask stuff:
instance/
.webassets-cache
# Scrapy stuff:
.scrapy
# Sphinx documentation
docs/_build/
# PyBuilder
target/
# Jupyter Notebook
.ipynb_checkpoints
# IPython
profile_default/
ipython_config.py
# pyenv
.python-version
# pipenv
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
# However, in case of collaboration, if having platform-specific dependencies or dependencies
# having no cross-platform support, pipenv may install dependencies that don't work, or not
# install all needed dependencies.
#Pipfile.lock
# PEP 582; used by e.g. github.com/David-OConnor/pyflow
__pypackages__/
# Celery stuff
celerybeat-schedule
celerybeat.pid
# SageMath parsed files
*.sage.py
# Environments
.env
.venv
env/
venv/
ENV/
env.bak/
venv.bak/
# Spyder project settings
.spyderproject
.spyproject
# Rope project settings
.ropeproject
# mkdocs documentation
/site
# mypy
.mypy_cache/
.dmypy.json
dmypy.json
# Pyre type checker
.pyre/
+82
View File
@@ -0,0 +1,82 @@
[dotbot_repo]: https://github.com/anishathalye/dotbot
## Dotbot ```git``` Plugin
Plugin for [Dotbot][dotbot_repo], that adds ```git``` directive, which allows you to clone or pull git repositories.
## Installation
1. Simply add this repo as a submodule of your dotfiles repository:
```
git submodule add https://github.com/DrDynamic/dotbot-git.git
```
2. Pass this folder (or directly git.py file) path with corresponding flag to your [Dotbot][dotbot_repo] script:
- ```-p /path/to/file/git.py```
or
- ```--plugin-dir /pato/to/plugin/folder```
## Requirements
This plugin needs git 2.22 or later to be installes.
Also please note, that this plugin clones repositories direcly into the given path.
No subfolders are created!
## Properties
| Name | Description | Required |
| --- | --- | --- |
| url | The URL to the remote repository | Required |
| branch | The branch to checkout after clone (or pull) | optional |
| commit | The commit to checkout after clone (or pull) | optional |
| method | Either clone, pull or clone-or-pull (see **Supported methods**) | optional |
| description | The description of the Repository (only for log output) | optional |
### Supported methods
| Method | Description |
| --- | --- |
| clone | Just clone the repository and checkout the configured branch / commit. Ignore that entry if that is alredy done.|
| pull | Just pull the existing directory. Failes if the directory doesn't exist or isnt a git repository |
| clone-or-pull | DEFAULT - Clones the repository if it doesnt exist or pulls changes if it does. |
## Supported task variants
```yaml
...
- git:
'/local/path/to/clone/to':
url: <url to repository>
branch: <name of the branch>
commit: <commit hash>
method: <clone|pull|clone-or-pull>
description: <name of the repository or something like that>
...
...
```
## Usage
### Example config
```yaml
...
- git:
'~/.oh-my-zsh/custom/plugins/zsh-autosuggestions':
url: 'https://github.com/zsh-users/zsh-autosuggestions'
description: 'oh my zsh - autosuggestions'
'~/.oh-my-zsh/custom/themes/powerlevel10k':
url: 'https://github.com/romkatv/powerlevel10k.git'
description: 'oh my zsh - powerlevel10k'
...
...
```
### Execution
```bash
"~/.dotfiles/bin/dotbot" -d "~/.dotfiles" -c "~/.dotfiles/packages.yaml" -p "~/.dotfiles/plugins/dotbot-git/git.py"
```
+173
View File
@@ -0,0 +1,173 @@
import subprocess, dotbot, os
from pprint import PrettyPrinter
class DotbotGit(dotbot.Plugin):
_directive = 'git'
def can_handle(self, directive):
return self._directive == directive
def handle(self, directive, data):
if directive != self._directive:
raise ValueError('git cannot handle directive %s' %
directive)
success = True
for clone_path in data:
repo_definition = data[clone_path]
repo = self.Repository(self._log)
repo.path = os.path.expanduser(clone_path)
if 'url' in repo_definition:
repo.url = repo_definition['url']
else:
success = False
self._log.error('Failed to clone repository! (no url specified)')
continue
if 'branch' in repo_definition:
repo.branch = repo_definition['branch']
if 'commit' in repo_definition:
repo.commit = repo_definition['commit']
if 'method' in repo_definition:
if repo_definition['method'] in ['clone', 'pull', 'clone-or-pull']:
repo.method = repo_definition['method']
else:
self._log.warning('Method '+repo_definition['method']
+'is not defined! (Will be ignored...)')
if 'description' in repo_definition:
repo.description = repo_definition['description']
if not repo.load():
success = False
return success
class Repository:
path=None
url=None
branch=None
commit=None
method='clone-or-pull'
description=None
_log = None
def __init__(self, _log):
self._log = _log
def load(self):
method = None
# check the load method to use
if self.method == 'clone':
method = 'clone'
if self.method == 'pull':
method = 'pull'
if self.method == 'clone-or-pull':
if self._repo_exists():
method = 'pull'
else:
method = 'clone'
# sanity checks
if method == 'clone':
if self._repo_exists():
method = None
self._log.lowinfo("Repository already exists! Won't clone " + self._get_description())
if method == 'pull':
if not self._repo_exists():
method = None
self._log.error("Repository doesn't exist! Woun't pull " + self._get_description())
# loading
success = True
if method == 'clone':
success = self._clone()
self._log.lowinfo('Cloned ' + self._get_description())
elif method == 'pull':
success = self._pull()
self._log.lowinfo('Pulled ' + self._get_description())
if self.branch is not None:
current_branch = self._get_current_branch()
if current_branch != self.branch:
self._checkout('branch')
if self.commit is not None:
current_commit = self._get_current_commit()
if current_commit != self.commit:
self.checkout('commit')
return success
def _clone(self):
if not os.path.isdir(self.path):
os.makedirs(self.path)
command = 'git clone --quiet '
command += self.url + ' ' + self.path
return self._run_command(command)
def _pull(self):
command = 'git --work-tree="' + self.path + '"'
command += ' --git-dir="' + self.path + '/.git"'
command += ' pull --quiet'
return self._run_command(command)
def _checkout(self, source='branch'):
if source == 'branch':
if self.branch is None:
return True
goto = self.branch
if source == 'commit':
if self.commit is None:
return True
goto = self.commit
command = 'git --work-tree="'+self.path+'"'
command += ' --git-dir="'+self.path+'/.git"'
command += ' checkout --quiet --force ' + goto
return self._run_command(command)
def _get_current_commit(self):
p = subprocess.Popen(
['git --git-dir="'+self.path+'/.git" rev-parse HEAD'],
shell=True,
stdout=subprocess.PIPE)
output = p.communicate()[0].decode()
if p.returncode == 0:
return output.strip()
return False
def _get_current_branch(self):
p = subprocess.Popen(
['git --git-dir="' + self.path + '/.git" branch --show-current'],
shell=True,
stdout=subprocess.PIPE)
output = p.communicate()[0].decode()
if p.returncode == 0:
return output.strip()
return False
def _run_command(self, command):
try:
subprocess.run(
[command],
shell=True,
check=True)
return True
except subprocess.CalledProcessError:
self._log.error('git command failed...')
return False
def _repo_exists(self):
return os.path.isdir(os.path.join(self.path, '.git'))
def _get_description(self):
if self.description is None:
return 'into ' + self.path
else:
return self.description