Example #1
0
def _send_msg():
    if git.GIT_COLA_TRACE == 'trace':
        msg = ('info: Trace enabled.  '
               'Many of commands reported with "trace" use git\'s stable '
               '"plumbing" API and are not intended for typical '
               'day-to-day use.  Here be dragons')
        cola.notifier().broadcast(signals.log_cmd, 0, msg)
Example #2
0
    def stash_save(self):
        """Saves the worktree in a stash

        This prompts the user for a stash name and creates
        a git stash named accordingly.
        """
        stash_name, ok = qtutils.prompt('Save Stash',
                                        'Enter a name for the stash')
        if not ok or not stash_name:
            return

        # Sanitize the stash name
        stash_name = utils.sanitize(stash_name)

        if stash_name in self.model.stash_names:
            qtutils.critical('Oops!',
                             'A stash named "%s" already exists' % stash_name)
            return

        args = []
        if self.view.keep_index.isChecked():
            args.append('--keep-index')
        args.append(stash_name)

        qtutils.log(*self.model.git.stash('save',
                                          with_stderr=True,
                                          with_status=True,
                                          *args))
        self.view.accept()
        cola.notifier().broadcast(signals.rescan)
Example #3
0
 def do(self):
     if self.keep_index:
         args = ["save", "--keep-index", self.stash_name]
     else:
         args = ["save", self.stash_name]
     status, output = git.stash(with_stderr=True, with_status=True, *args)
     cola.notifier().broadcast(signals.log_cmd, status, output)
Example #4
0
 def unstage(self):
     """Unstage selected files, or all files if no selection exists."""
     paths = cola.selection_model().staged
     if not paths:
         cola.notifier().broadcast(signals.unstage_all)
     else:
         cola.notifier().broadcast(signals.unstage, paths)
Example #5
0
def start():
    global _thread
    if not AVAILABLE:
        if utils.is_win32():
            msg = ('file notification: disabled\n'
                   'Note: install pywin32 to enable.\n')
        elif utils.is_linux():
            msg = ('inotify: disabled\n'
                   'Note: install python-pyinotify to enable inotify.\n')
        else:
            return

        if utils.is_debian():
            msg += ('On Debian systems '
                    'try: sudo aptitude install python-pyinotify')
        cola.notifier().broadcast(signals.log_cmd, 0, msg)
        return

    # Start the notification thread
    _thread = GitNotifier()
    _thread.start()
    if utils.is_win32():
        msg = 'file notification: enabled'
    else:
        msg = 'inotify support: enabled'
    cola.notifier().broadcast(signals.log_cmd, 0, msg)
Example #6
0
    def _update_view(self):
        """Update the title with the current branch and directory name."""
        title = '%s [%s]' % (self.model.project,
                             self.model.currentbranch)
        if self.mode in (self.model.mode_diff, self.model.mode_diff_expr):
            title += ' *** diff mode***'
        elif self.mode == self.model.mode_review:
            title += ' *** review mode***'
        elif self.mode == self.model.mode_amend:
            title += ' *** amending ***'
        self.setWindowTitle(title)

        if self.mode != self.model.mode_amend:
            self.amend_checkbox.blockSignals(True)
            self.amend_checkbox.setChecked(False)
            self.amend_checkbox.blockSignals(False)

        if not self.model.read_only() and self.mode != self.model.mode_amend:
            # Check if there's a message file in .git/
            merge_msg_path = gitcmds.merge_message_path()
            if merge_msg_path is None:
                return
            merge_msg_hash = utils.checksum(merge_msg_path)
            if merge_msg_hash == self.merge_message_hash:
                return
            self.merge_message_hash = merge_msg_hash
            cola.notifier().broadcast(signals.load_commit_message,
                                      merge_msg_path)
Example #7
0
 def do(self):
     if self.keep_index:
         args = ['save', '--keep-index', self.stash_name]
     else:
         args = ['save', self.stash_name]
     status, output = git.stash(with_stderr=True, with_status=True, *args)
     cola.notifier().broadcast(signals.log_cmd, status, output)
Example #8
0
def open_repo():
    """Spawn a new cola session."""
    dirname = qtutils.opendir_dialog('Open Git Repository...',
                                     cola.model().getcwd())
    if not dirname:
        return
    cola.notifier().broadcast(signals.open_repo, dirname)
Example #9
0
 def do(self):
     if self.index:
         args = ['apply', '--index', self.selection]
     else:
         args = ['apply', self.selection]
     status, output = git.stash(with_stderr=True, with_status=True, *args)
     cola.notifier().broadcast(signals.log_cmd, status, output)
Example #10
0
    def show_selection(self):
        """Show the selected item."""
        # Sync the selection model
        cola.selection_model().set_selection(self.selection())

        selection = self.selected_indexes()
        if not selection:
            return
        category, idx = selection[0]
        # A header item e.g. 'Staged', 'Modified', etc.
        if category == self.idx_header:
            signal = {
                self.idx_staged: signals.staged_summary,
                self.idx_modified: signals.modified_summary,
                self.idx_unmerged: signals.unmerged_summary,
                self.idx_untracked: signals.untracked_summary,
            }.get(idx, signals.diffstat)
            cola.notifier().broadcast(signal)
        # A staged file
        elif category == self.idx_staged:
            cola.notifier().broadcast(signals.diff_staged, self.staged())

        # A modified file
        elif category == self.idx_modified:
            cola.notifier().broadcast(signals.diff, self.modified())

        elif category == self.idx_unmerged:
            cola.notifier().broadcast(signals.diff, self.unmerged())

        elif category == self.idx_untracked:
            cola.notifier().broadcast(signals.show_untracked, self.unstaged())
Example #11
0
 def do(self):
     if self.index:
         args = ["apply", "--index", self.selection]
     else:
         args = ["apply", self.selection]
     status, output = git.stash(with_stderr=True, with_status=True, *args)
     cola.notifier().broadcast(signals.log_cmd, status, output)
Example #12
0
def open_repo():
    """Spawn a new cola session."""
    dirname = qtutils.opendir_dialog('Open Git Repository...',
                                     cola.model().getcwd())
    if not dirname:
        return
    cola.notifier().broadcast(signals.open_repo, dirname)
Example #13
0
    def _revert_unstaged_edits(self, staged=False):
        if not self.m.undoable():
            return
        if staged:
            items_to_undo = self.staged()
        else:
            items_to_undo = self.modified()

        if items_to_undo:
            if not qtutils.confirm('Revert Unstaged Changes?',
                                   'This operation drops unstaged changes.'
                                   '\nThese changes cannot be recovered.',
                                   'Revert the unstaged changes?',
                                   'Revert Unstaged Changes',
                                   default=True,
                                   icon=qtutils.icon('undo.svg')):
                return
            args = []
            if not staged and self.m.amending():
                args.append(self.m.head)
            cola.notifier().broadcast(signals.checkout,
                                      args + ['--'] + items_to_undo)
        else:
            qtutils.log(1, self.tr('No files selected for '
                                   'checkout from HEAD.'))
Example #14
0
    def _update_callback(self):
        """Update the title with the current branch and directory name."""
        branch = self.model.currentbranch
        curdir = core.decode(os.getcwd())
        msg = 'Repository: %s\nBranch: %s' % (curdir, branch)
        self.commitdockwidget.setToolTip(msg)

        title = '%s: %s' % (self.model.project, branch)
        if self.mode == self.model.mode_amend:
            title += ' ** amending **'
        self.setWindowTitle(title)

        self.commitmsgeditor.set_mode(self.mode)

        if not self.model.amending():
            # Check if there's a message file in .git/
            merge_msg_path = gitcmds.merge_message_path()
            if merge_msg_path is None:
                return
            merge_msg_hash = utils.checksum(core.decode(merge_msg_path))
            if merge_msg_hash == self.merge_message_hash:
                return
            self.merge_message_hash = merge_msg_hash
            cola.notifier().broadcast(signals.load_commit_message,
                                      core.decode(merge_msg_path))
Example #15
0
    def _update_callback(self):
        """Update the title with the current branch and directory name."""
        branch = self.model.currentbranch
        curdir = core.decode(os.getcwd())
        msg = 'Repository: %s\nBranch: %s' % (curdir, branch)
        self.commitdockwidget.setToolTip(msg)

        title = '%s [%s]' % (self.model.project, branch)
        if self.mode in (self.model.mode_diff, self.model.mode_diff_expr):
            title += ' *** diff mode***'
        elif self.mode == self.model.mode_review:
            title += ' *** review mode***'
        elif self.mode == self.model.mode_amend:
            title += ' *** amending ***'
        self.setWindowTitle(title)

        if self.mode != self.model.mode_amend:
            self.amend_checkbox.blockSignals(True)
            self.amend_checkbox.setChecked(False)
            self.amend_checkbox.blockSignals(False)

        if not self.model.read_only() and self.mode != self.model.mode_amend:
            # Check if there's a message file in .git/
            merge_msg_path = gitcmds.merge_message_path()
            if merge_msg_path is None:
                return
            merge_msg_hash = utils.checksum(core.decode(merge_msg_path))
            if merge_msg_hash == self.merge_message_hash:
                return
            self.merge_message_hash = merge_msg_hash
            cola.notifier().broadcast(signals.load_commit_message,
                                      core.decode(merge_msg_path))
Example #16
0
def _send_msg():
    if git.GIT_COLA_TRACE == 'trace':
        msg = ('info: Trace enabled.  '
               'Many of commands reported with "trace" use git\'s stable '
               '"plumbing" API and are not intended for typical '
               'day-to-day use.  Here be dragons')
        cola.notifier().broadcast(signals.log_cmd, 0, msg)
Example #17
0
def start():
    global _thread
    if not AVAILABLE:
        if utils.is_win32():
            msg = ('file notification: disabled\n'
                   'Note: install pywin32 to enable.\n')
        elif utils.is_linux():
            msg = ('inotify: disabled\n'
                   'Note: install python-pyinotify to enable inotify.\n')
        else:
            return

        if utils.is_debian():
            msg += ('On Debian systems '
                    'try: sudo aptitude install python-pyinotify')
        cola.notifier().broadcast(signals.log_cmd, 0, msg)
        return

    # Start the notification thread
    _thread = GitNotifier()
    _thread.start()
    if utils.is_win32():
        msg = 'file notification: enabled'
    else:
        msg = 'inotify support: enabled'
    cola.notifier().broadcast(signals.log_cmd, 0, msg)
Example #18
0
def load_commitmsg(parent):
    """Load a commit message from a file."""
    filename = qtutils.open_dialog(parent,
                                   'Load Commit Message...',
                                   cola.model().getcwd())
    if filename:
        cola.notifier().broadcast(signals.load_commit_message, filename)
Example #19
0
    def _initialize(self):
        """Iterate over git-ls-tree and create GitTreeItems."""
        status, output = git.ls_tree('--full-tree',
                                     '-r',
                                     '-t',
                                     '-z',
                                     self.ref,
                                     with_status=True,
                                     with_stderr=True)
        if status != 0:
            cola.notifier().broadcast(signals.log_cmd, status, output)
            return

        if not output:
            return

        for line in core.decode(output[:-1]).split('\0'):
            # .....6 ...4 ......................................40
            # 040000 tree c127cde9a0c644a3a8fef449a244f47d5272dfa6	relative
            # 100644 blob 139e42bf4acaa4927ec9be1ec55a252b97d3f1e2	relative/path
            objtype = line[7]
            relpath = line[6 + 1 + 4 + 1 + 40 + 1:]
            if objtype == 't':
                parent = self.dir_entries[utils.dirname(relpath)]
                self.add_directory(parent, relpath)
            elif objtype == 'b':
                self.add_file(relpath)
Example #20
0
    def create_tag(self):
        """Verifies inputs and emits a notifier tag message."""

        revision = self.revision.value()
        tag_name = self.tag_name.value()
        tag_msg = self.tag_msg.value()
        sign_tag = self.sign_tag.isChecked()

        if not revision:
            critical('Missing Revision', 'Please specify a revision to tag.')
            return
        elif not tag_name:
            critical('Missing Name', 'Please specify a name for the new tag.')
            return
        elif (sign_tag and not tag_msg and
                not qtutils.confirm('Missing Tag Message',
                                    'Tag-signing was requested but the tag '
                                    'message is empty.',
                                    'An unsigned, lightweight tag will be '
                                    'created instead.\n'
                                    'Create an unsigned tag?',
                                    'Create Unsigned Tag',
                                    default=False,
                                    icon=qtutils.save_icon())):
            return

        cola.notifier().broadcast(signals.tag, tag_name, revision,
                                  sign=sign_tag, message=tag_msg)
        information('Tag Created', 'Created a new tag named "%s"' % tag_name,
                    details=tag_msg or None)
        self.accept()
Example #21
0
    def clicked(self, item=None, idx=None):
        """Called when a repo status tree item is clicked.

        This handles the behavior where clicking on the icon invokes
        the a context-specific action.

        """
        if self.m.read_only():
            return

        # Sync the selection model
        staged, modified, unmerged, untracked = self.selection()
        cola.selection_model().set_selection(staged, modified,
                                             unmerged, untracked)

        # Clear the selection if an empty area was clicked
        selection = self.selected_indexes()
        if not selection:
            if self.mode == self.m.mode_amend:
                cola.notifier().broadcast(signals.set_diff_text, '')
            else:
                cola.notifier().broadcast(signals.reset_mode)
            self.blockSignals(True)
            self.clearSelection()
            self.blockSignals(False)
            return

        if staged:
            qtutils.set_clipboard(staged[0])
        elif modified:
            qtutils.set_clipboard(modified[0])
        elif unmerged:
            qtutils.set_clipboard(unmerged[0])
        elif untracked:
            qtutils.set_clipboard(untracked[0])
Example #22
0
 def create_tag(self):
     """Verifies inputs and emits a notifier tag message."""
     if not self.model.tag_name:
         cola.notifier().broadcast(signals.critical,
                                   'Missing Name',
                                   'You must name the tag.')
         return
     if (self.model.sign_tag and
             not self.model.tag_msg and
             not qtutils.confirm('Missing Tag Message',
                                 'Tag-signing was requested but the tag '
                                 'message is empty.',
                                 'An unsigned, lightweight tag will be '
                                 'created instead.\n'
                                 'Create an unsigned tag?',
                                 'Create Unsigned Tag',
                                 default=False,
                                 icon=qtutils.save_icon())):
         return
     cola.notifier().broadcast(signals.tag,
                               self.model.tag_name,
                               self.model.revision_item,
                               sign=self.model.sign_tag,
                               message=self.model.tag_msg)
     self.view.accept()
Example #23
0
def branch_delete():
    """Launch the 'Delete Branch' dialog."""
    branch = choose_from_combo('Delete Branch',
                               cola.model().local_branches)
    if not branch:
        return
    cola.notifier().broadcast(signals.delete_branch, branch)
Example #24
0
def grep():
    """Prompt and use 'git grep' to find the content."""
    # This should be a command in cola.cmds.
    txt, ok = qtutils.prompt('grep')
    if not ok:
        return
    cola.notifier().broadcast(signals.grep, txt)
Example #25
0
def checkout_branch():
    """Launch the 'Checkout Branch' dialog."""
    branch = choose_from_combo('Checkout Branch',
                               cola.model().local_branches)
    if not branch:
        return
    cola.notifier().broadcast(signals.checkout_branch, branch)
Example #26
0
    def tree_click(self, event):
        """
        Called when a repo status tree item is clicked.

        This handles the behavior where clicking on the icon invokes
        the same appropriate action.

        """
        result = QtGui.QTreeWidget.mouseReleaseEvent(self.tree, event)

        # Sync the selection model
        s, m, um, ut = self.selection()
        cola.selection_model().set_selection(s, m, um, ut)

        # Get the item that was clicked
        item = self.tree.itemAt(event.pos())
        if not item:
            # Nothing was clicked -- reset the display and return
            cola.notifier().broadcast(signals.reset_mode)
            items = self.tree.selectedItems()
            self.tree.blockSignals(True)
            for i in items:
                self.tree.setItemSelected(i, False)
            self.tree.blockSignals(False)
        return result
Example #27
0
 def unstage(self):
     """Unstage selected files, or all files if no selection exists."""
     paths = cola.selection_model().staged
     if not paths:
         cola.notifier().broadcast(signals.unstage_all)
     else:
         cola.notifier().broadcast(signals.unstage, paths)
Example #28
0
 def cherry_pick(self):
     """Launch the 'Cherry-Pick' dialog."""
     revs, summaries = gitcmds.log_helper(all=True)
     commits = select_commits('Cherry-Pick Commit',
                              revs, summaries, multiselect=False)
     if not commits:
         return
     cola.notifier().broadcast(signals.cherry_pick, commits)
Example #29
0
 def stash_show(self):
     """Shows the current stash in the main view."""
     selection = self.selected_stash()
     if not selection:
         return
     diffstat = self.model.git.stash('show', selection)
     diff = self.model.git.stash('show', '-p', selection)
     cola.notifier().broadcast(signals.diff_text, '%s\n\n%s' % (diffstat, diff))
Example #30
0
def diff_expression():
    """Diff using an arbitrary expression."""
    expr = choose_from_combo('Enter Diff Expression',
                             cola.model().all_branches() +
                             cola.model().tags)
    if not expr:
        return
    cola.notifier().broadcast(signals.diff_expr_mode, expr)
Example #31
0
 def _create_patch(self):
     items = self.selectedItems()
     if not items:
         return
     items.reverse()
     sha1s = [item.commit.sha1 for item in items]
     all_sha1s = [c.sha1 for c in self._commits]
     cola.notifier().broadcast(signals.format_patch, sha1s, all_sha1s)
Example #32
0
 def _create_patch(self):
     items = self.selectedItems()
     if not items:
         return
     selected_commits = sort_by_generation([n.commit for n in items])
     sha1s = [c.sha1 for c in selected_commits]
     all_sha1s = [c.sha1 for c in self._commits]
     cola.notifier().broadcast(signals.format_patch, sha1s, all_sha1s)
Example #33
0
def review_branch():
    """Diff against an arbitrary revision, branch, tag, etc."""
    branch = choose_from_combo('Select Branch, Tag, or Commit-ish',
                               cola.model().all_branches() +
                               cola.model().tags)
    if not branch:
        return
    cola.notifier().broadcast(signals.review_branch_mode, branch)
Example #34
0
 def branch_diff(self):
     """Diff against an arbitrary revision, branch, tag, etc."""
     branch = choose_from_combo('Select Branch, Tag, or Commit-ish',
                                ['HEAD^'] +
                                self.model.all_branches() +
                                self.model.tags)
     if not branch:
         return
     cola.notifier().broadcast(signals.diff_mode, branch)
Example #35
0
 def export_patches(self):
     """Run 'git format-patch' on a list of commits."""
     revs, summaries = gitcmds.log_helper()
     to_export = select_commits('Export Patches', revs, summaries)
     if not to_export:
         return
     to_export.reverse()
     revs.reverse()
     cola.notifier().broadcast(signals.format_patch, to_export, revs)
Example #36
0
def export_patches():
    """Run 'git format-patch' on a list of commits."""
    revs, summaries = gitcmds.log_helper()
    to_export = select_commits('Export Patches', revs, summaries)
    if not to_export:
        return
    to_export.reverse()
    revs.reverse()
    cola.notifier().broadcast(signals.format_patch, to_export, revs)
Example #37
0
 def event(self, msg):
     """Overrides event() to handle custom inotify events."""
     if not AVAILABLE:
         return
     if msg.type() == INOTIFY_EVENT:
         cola.notifier().broadcast(signals.rescan)
         return True
     else:
         return False
Example #38
0
 def process_diff_selection(self,
                            selected=False,
                            staged=True,
                            apply_to_worktree=False,
                            reverse=False):
     """Implement un/staging of selected lines or sections."""
     offset, selection = self.offset_and_selection()
     cola.notifier().broadcast(signals.apply_diff_selection, staged,
                               selected, offset, selection,
                               apply_to_worktree)
Example #39
0
def cherry_pick():
    """Launch the 'Cherry-Pick' dialog."""
    revs, summaries = gitcmds.log_helper(all=True)
    commits = select_commits('Cherry-Pick Commit',
                             revs,
                             summaries,
                             multiselect=False)
    if not commits:
        return
    cola.notifier().broadcast(signals.cherry_pick, commits)
Example #40
0
    def selectionChanged(self, old_selection, new_selection):
        """Override selectionChanged to update available actions."""
        result = QtGui.QTreeView.selectionChanged(self, old_selection, new_selection)
        self.update_actions()
        paths = self.sync_selection()

        if paths and self.model().path_is_interesting(paths[0]):
            cached = paths[0] in cola.model().staged
            cola.notifier().broadcast(signals.diff, paths, cached)
        return result
Example #41
0
 def _launch_difftool(self):
     staged, modified, unmerged, untracked = self.selection()
     if staged:
         selection = staged
     elif unmerged:
         selection = unmerged
     elif modified:
         selection = modified
     else:
         return
     cola.notifier().broadcast(signals.difftool, bool(staged), selection)
Example #42
0
    def selectionChanged(self, old_selection, new_selection):
        """Override selectionChanged to update available actions."""
        result = QtGui.QTreeView.selectionChanged(self, old_selection,
                                                  new_selection)
        self.update_actions()
        paths = self.sync_selection()

        if paths and self.model().path_is_interesting(paths[0]):
            cached = paths[0] in cola.model().staged
            cola.notifier().broadcast(signals.diff, paths, cached)
        return result
Example #43
0
 def revert(self):
     """Signal that we should revert changes to a path."""
     if not qtutils.confirm('Revert Uncommitted Changes?',
                            'This operation drops uncommitted changes.'
                            '\nThese changes cannot be recovered.',
                            'Revert the uncommitted changes?',
                            'Revert Uncommitted Changes',
                            default=True,
                            icon=qtutils.icon('undo.svg')):
         return
     paths = self.selected_tracked_paths()
     cola.notifier().broadcast(signals.checkout, ['HEAD', '--'] + paths)
Example #44
0
    def _process_selection(self):
        s = self.selection()
        if s.staged:
            cola.notifier().broadcast(signals.unstage, s.staged)

        unstaged = []
        if s.unmerged:
            unstaged.extend(s.unmerged)
        if s.modified:
            unstaged.extend(s.modified)
        if s.untracked:
            unstaged.extend(s.untracked)
        if unstaged:
            cola.notifier().broadcast(signals.stage, unstaged)
Example #45
0
 def dropEvent(self, event):
     """Apply dropped patches with git-am"""
     event.accept()
     urls = event.mimeData().urls()
     if not urls:
         return
     paths = map(lambda x: unicode(x.path()), urls)
     patches = [p for p in paths if p.endswith('.patch')]
     dirs = [p for p in paths if os.path.isdir(p)]
     dirs.sort()
     for d in dirs:
         patches.extend(self._gather_patches(d))
     # Broadcast the patches to apply
     cola.notifier().broadcast(signals.apply_patches, patches)
Example #46
0
def register_for_signals():
    # Register globally with the notifier
    notifier = cola.notifier()
    notifier.connect(signals.confirm, confirm)
    notifier.connect(signals.critical, critical)
    notifier.connect(signals.information, information)
    notifier.connect(signals.question, question)
Example #47
0
 def _revert_uncommitted_edits(self):
     items_to_undo = self.modified()
     if items_to_undo:
         if not qtutils.confirm('Revert Uncommitted Changes?',
                                'This operation drops uncommitted changes.'
                                '\nThese changes cannot be recovered.',
                                'Revert the uncommitted changes?',
                                'Revert Uncommitted Changes',
                                default=True,
                                icon=qtutils.icon('undo.svg')):
             return
         cola.notifier().broadcast(signals.checkout,
                                   [self.m.head, '--'] + items_to_undo)
     else:
         qtutils.log(1, self.tr('No files selected for '
                                'checkout from HEAD.'))
Example #48
0
 def do(self):
     fp = open(core.encode(self.filename), 'wb')
     cmd = ['git', 'archive', '--format='+self.fmt]
     if self.fmt in ('tgz', 'tar.gz'):
         cmd.append('-9')
     if self.prefix:
         cmd.append('--prefix=' + self.prefix)
     cmd.append(self.ref)
     proc = utils.start_command(cmd, stdout=fp)
     out, err = proc.communicate()
     fp.close()
     if not out:
         out = ''
     if err:
         out += err
     status = proc.returncode
     cola.notifier().broadcast(signals.log_cmd, status, out)
Example #49
0
 def do(self):
     squash = self.squash
     revision = self.revision
     no_commit = self.no_commit
     status, output = self.context.merge(revision, no_commit, squash)
     notifier = cola.notifier()
     notifier.broadcast(signals.log_cmd, status, output)
     self.context.update_status()
Example #50
0
    def do(self):
        context = self.context
        ref = core.encode(context.ref)
        relpath = core.encode(context.relpath)

        cmd = ['git', 'show', '%s:%s' % (ref, relpath)]
        fp = open(core.encode(context.filename), 'wb')
        proc = utils.start_command(cmd, stdout=fp)

        out, err = proc.communicate()
        fp.close()

        status = proc.returncode
        msg = ('Saved "%s" from %s to "%s"' %
               (context.relpath, context.ref, context.filename))
        cola.notifier().broadcast(signals.log_cmd, status, msg)

        self.factory.prompt_user(signals.information, 'File Saved',
                                 'File saved to "%s"' % context.filename)
Example #51
0
    def commit(self):
        """Attempt to create a commit from the index and commit message."""
        if not bool(self.summary.value()):
            # Describe a good commit message
            error_msg = tr(
                ''
                'Please supply a commit message.\n\n'
                'A good commit message has the following format:\n\n'
                '- First line: Describe in one sentence what you did.\n'
                '- Second line: Blank\n'
                '- Remaining lines: Describe why this change is good.\n')
            log(1, error_msg)
            cola.notifier().broadcast(signals.information,
                                      'Missing Commit Message', error_msg)
            return

        msg = self.commit_message(raw=False)

        if not self.model.staged:
            error_msg = tr(
                ''
                'No changes to commit.\n\n'
                'You must stage at least 1 file before you can commit.')
            if self.model.modified:
                informative_text = tr('Would you like to stage and '
                                      'commit all modified files?')
                if not confirm('Stage and commit?',
                               error_msg,
                               informative_text,
                               'Stage and Commit',
                               default=False,
                               icon=save_icon()):
                    return
            else:
                cola.notifier().broadcast(signals.information,
                                          'Nothing to commit', error_msg)
                return
            cola.notifier().broadcast(signals.stage_modified)

        # Warn that amending published commits is generally bad
        amend = self.amend_action.isChecked()
        if (amend and self.model.is_commit_published() and
                not confirm('Rewrite Published Commit?',
                            'This commit has already been published.\n'
                            'This operation will rewrite published history.\n'
                            'You probably don\'t want to do this.',
                            'Amend the published commit?',
                            'Amend Commit',
                            default=False,
                            icon=save_icon())):
            return
        # Perform the commit
        cola.notifier().broadcast(signals.commit, amend, msg)
Example #52
0
    def _delete_files(self):
        files = self.untracked()
        count = len(files)
        if count == 0:
            return

        title = 'Delete Files?'
        msg = self.tr('The following files will be deleted:\n\n')

        fileinfo = subprocess.list2cmdline(files)
        if len(fileinfo) > 2048:
            fileinfo = fileinfo[:2048].rstrip() + '...'
        msg += fileinfo

        info_txt = unicode(self.tr('Delete %d file(s)?')) % count
        ok_txt = 'Delete Files'

        if qtutils.confirm(title, msg, info_txt, ok_txt,
                           default=True,
                           icon=qtutils.discard_icon()):
            cola.notifier().broadcast(signals.delete, files)
Example #53
0
    def clicked(self, item=None, idx=None):
        """Called when a repo status tree item is clicked.

        This handles the behavior where clicking on the icon invokes
        the a context-specific action.

        """
        # Sync the selection model
        s = self.selection()
        cola.selection_model().set_selection(s)

        # Clear the selection if an empty area was clicked
        selection = self.selected_indexes()
        if not selection:
            if self.m.amending():
                cola.notifier().broadcast(signals.set_diff_text, '')
            else:
                cola.notifier().broadcast(signals.reset_mode)
            self.blockSignals(True)
            self.clearSelection()
            self.blockSignals(False)
            return
Example #54
0
def clone_repo(spawn=True):
    """
    Present GUI controls for cloning a repository

    A new cola session is invoked when 'spawn' is True.

    """
    url, ok = qtutils.prompt('Path or URL to clone (Env. $VARS okay)')
    url = os.path.expandvars(core.encode(url))
    if not ok or not url:
        return None
    try:
        # Pick a suitable basename by parsing the URL
        newurl = url.replace('\\', '/')
        default = newurl.rsplit('/', 1)[-1]
        if default == '.git':
            # The end of the URL is /.git, so assume it's a file path
            default = os.path.basename(os.path.dirname(newurl))
        if default.endswith('.git'):
            # The URL points to a bare repo
            default = default[:-4]
        if url == '.':
            # The URL is the current repo
            default = os.path.basename(os.getcwd())
        if not default:
            raise
    except:
        cola.notifier().broadcast(signals.information, 'Error Cloning',
                                  'Could not parse: "%s"' % url)
        qtutils.log(1, 'Oops, could not parse git url: "%s"' % url)
        return None

    # Prompt the user for a directory to use as the parent directory
    msg = 'Select a parent directory for the new clone'
    dirname = qtutils.opendir_dialog(msg, cola.model().getcwd())
    if not dirname:
        return None
    count = 1
    dirname = core.decode(dirname)
    destdir = os.path.join(dirname, core.decode(default))
    olddestdir = destdir
    if os.path.exists(destdir):
        # An existing path can be specified
        msg = ('"%s" already exists, cola will create a new directory' %
               destdir)
        cola.notifier().broadcast(signals.information, 'Directory Exists', msg)

    # Make sure the new destdir doesn't exist
    while os.path.exists(destdir):
        destdir = olddestdir + str(count)
        count += 1
    cola.notifier().broadcast(signals.clone,
                              core.decode(url),
                              destdir,
                              spawn=spawn)
    return destdir
Example #55
0
 def editor(self):
     """Signal that we should edit selected paths using an external editor."""
     cola.notifier().broadcast(signals.edit, self.selected_paths())
Example #56
0
 def difftool(self):
     """Signal that we should launch difftool on a path."""
     cola.notifier().broadcast(signals.difftool, False,
                               self.selected_tracked_paths())
Example #57
0
 def untrack_selected(self):
     """Signal that we should stage selected paths."""
     cola.notifier().broadcast(signals.untrack,
                               self.selected_tracked_paths())