Source code for wxyz.dvcs.tools.tool_heads

"""baseline tools for working with heads"""

import ipywidgets as W
import traitlets as T
from jinja2 import Template

from ..repos.repo_base import Repo
from .utils import BTN_ICON_DEFAULTS

DEFAULT_STATUS_TEMPLATE = """
<i class="fa fa-code-fork"></i> {{ repo.head }}
<i class="fa fa-hashtag"></i>
<code title="{{repo.head_hash}}">{{ repo.head_hash[:7] }}</code>
{% if repo.changes %}
<i class="fa fa-pencil-square"></i> {{ repo.changes | count }} changes
{% endif %}
"""


[docs]class HeadStatus(W.HBox): """a status bar""" # pylint: disable=fixme repo = T.Instance(Repo) # todo: break up more for styling html = T.Instance(W.HTML, kw={}) template = T.Instance(Template) def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.children = [self.html] # todo: handle repo change self.repo.observe(self._on_repo_update) def _on_repo_update(self, _change): """update the status bar""" self.html.value = self.template.render(repo=self.repo) @T.default("template") def _default_template(self): """make a default template""" return Template(DEFAULT_STATUS_TEMPLATE)
[docs]class HeadPicker(W.HBox): """a simple dropdown-based picker of current DVCS heads""" # pylint: disable=unused-argument repo = T.Instance(Repo) picker = T.Instance(W.DOMWidget) refresh_btn = T.Instance(W.Button) checkout_btn = T.Instance(W.Button) _repo_link = None def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.refresh_btn.on_click(self.refresh) self.checkout_btn.on_click(self.checkout) self.picker.observe(self._update_picker_value, "options") self.children = [self.picker, self.refresh_btn, self.checkout_btn]
[docs] def refresh(self, *args, **kwargs): """refresh the heads""" # pylint: disable=protected-access if self.repo is not None: self.repo._update_heads()
[docs] def checkout(self, *args, **kwargs): """check out a ref""" self.repo.checkout(self.picker.value)
def _update_picker_value(self, *args, **kwargs): """ensure the right option is selected""" self.picker.value = self.repo.head @T.observe("repo") def _on_repo_changed(self, change): """react to the repo changing""" if self._repo_link is not None: self._repo_link.unlink() self._repo_link = None if change.new: self._repo_link = T.dlink( (change.new, "heads"), (self.picker, "options"), self._format_head_options, ) def _format_head_options(self, heads): marks = {self.repo.head: "*"} return { f"""{marks.get(name, "")}{name} [{commit[:7]}]""": name for name, commit in heads.items() } @T.default("picker") def _default_picker(self): """a default picker""" return W.Dropdown(description="Head") @T.default("refresh_btn") def _default_refresh_btn(self): """a default refresh button""" return W.Button(icon="refresh", **BTN_ICON_DEFAULTS) @T.default("checkout_btn") def _default_checkout_btn(self): """a default checkout button""" return W.Button(icon="check-circle", **BTN_ICON_DEFAULTS)
[docs]class Brancher(W.HBox): """Create a new branch from the current commit""" # pylint: disable=unused-argument repo = T.Instance(Repo) create_btn = T.Instance(W.Button) branch_name = T.Instance(W.Text) _repo_link = None def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.create_btn.on_click(self.create) T.dlink( (self.branch_name, "value"), (self.create_btn, "disabled"), lambda x: not x ) self.children = [self.branch_name, self.create_btn]
[docs] def create(self, *args, **kwargs): """actually create the new branch""" self.repo.branch(self.branch_name.value) self.branch_name.value = ""
@T.default("create_btn") def _default_create_btn(self): """a default create button""" return W.Button(icon="plus", **BTN_ICON_DEFAULTS) @T.default("branch_name") def _default_branch_name(self): """a default branch name editor""" return W.Text(description="New Branch")