def _action_completed(self, task, status, output): # Grab the results of the action and finish up if task in self._tasks: self._tasks.remove(task) if not output: # git fetch --tags --verbose doesn't print anything... output = self.tr('Already up-to-date.') # Force the status to 1 so that we always display the log qtutils.log(1, output) self.progress.close() QtGui.QApplication.restoreOverrideCursor() if status != 0 and self.action == 'push': message = 'Error pushing to "%s".\n\nPull first?' % self.model.remotename qtutils.critical('Push Error', message=message, details=output) else: title = self.view.windowTitle() if status == 0: result = 'succeeded' else: result = 'returned exit status %d' % status message = '"git %s" %s' % (self.action, result) qtutils.information(title, message=message, details=output) self.view.accept()
def _new(self): dlg = QtGui.QFileDialog(self) dlg.setFileMode(QtGui.QFileDialog.Directory) dlg.setOption(QtGui.QFileDialog.ShowDirsOnly) if dlg.exec_() != QtGui.QFileDialog.Accepted: return paths = dlg.selectedFiles() if not paths: return upath = unicode(paths[0]) if not upath: return path = core.encode(unicode(paths[0])) # Avoid needlessly calling `git init`. if git.is_git_dir(path): # We could prompt here and confirm that they really didn't # mean to open an existing repository, but I think # treating it like an "Open" is a sensible DWIM answer. self._gitdir = upath self.accept() return os.chdir(path) status, out, err = utils.run_command(['git', 'init']) if status != 0: title = 'Error Creating Repository' msg = 'git init returned exit status %d' % status details = 'output:\n%s\n\nerrors:\n%s' % (out, err) qtutils.critical(title, msg, details) else: self._gitdir = upath self.accept()
def show_shortcuts(): try: from PyQt4 import QtWebKit except ImportError: # redhat disabled QtWebKit in their qt build but don't punish the # users qtutils.critical( N_('This PyQt4 does not include QtWebKit.\n' 'The keyboard shortcuts feature is unavailable.')) return try: html = show_shortcuts.html except AttributeError: hotkeys_html = resources.doc(N_('hotkeys.html')) html = show_shortcuts.html = core.read(hotkeys_html) try: widget = show_shortcuts.widget except AttributeError: parent = qtutils.active_window() widget = show_shortcuts.widget = QtGui.QDialog(parent) widget.setWindowModality(Qt.WindowModal) widget.setWindowTitle(N_('Shortcuts')) web = QtWebKit.QWebView(parent) web.setHtml(html) layout = qtutils.hbox(defs.no_margin, defs.spacing, web) widget.setLayout(layout) widget.resize(800, min(parent.height(), 600)) qtutils.add_action(widget, N_('Close'), widget.accept, hotkeys.QUESTION, *hotkeys.ACCEPT) widget.show() return widget
def action_completed(self, task, status, output): # Grab the results of the action and finish up self.progress_thread.stop() self.progress_thread.wait() if task in self.tasks: self.tasks.remove(task) already_up_to_date = self.tr('Already up-to-date.') if not output: # git fetch --tags --verbose doesn't print anything... output = already_up_to_date self.setEnabled(True) self.progress.close() QtGui.QApplication.restoreOverrideCursor() result = 'returned exit status %d' % status message = '"git %s" %s' % (self.action.lower(), result) if output: message += '\n\n' + output # Force the status to 1 so that we always display the log qtutils.log(1, message) if status == 0: self.accept() return if self.action == PUSH: message += '\n\nHave you rebased/pulled lately?' qtutils.critical(self.windowTitle(), message=message, details=output)
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(N_('Missing Revision'), N_('Please specify a revision to tag.')) return elif not tag_name: critical(N_('Missing Name'), N_('Please specify a name for the new tag.')) return elif (sign_tag and not tag_msg and not qtutils.confirm(N_('Missing Tag Message'), N_('Tag-signing was requested but the tag ' 'message is empty.'), N_('An unsigned, lightweight tag will be ' 'created instead.\n' 'Create an unsigned tag?'), N_('Create Unsigned Tag'), default=False, icon=qtutils.save_icon())): return cmds.do(cmds.Tag, tag_name, revision, sign=sign_tag, message=tag_msg) information(N_('Tag Created'), N_('Created a new tag named "%s"') % tag_name, details=tag_msg or None) self.accept()
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)
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()
def show_shortcuts(): try: from PyQt4 import QtWebKit except ImportError: # redhat disabled QtWebKit in their qt build but don't punish the # users qtutils.critical(N_('This PyQt4 does not include QtWebKit.\n' 'The keyboard shortcuts feature is unavailable.')) return try: html = show_shortcuts.html except AttributeError: hotkeys_html = resources.doc(N_('hotkeys.html')) html = show_shortcuts.html = core.read(hotkeys_html) try: widget = show_shortcuts.widget except AttributeError: parent = qtutils.active_window() widget = show_shortcuts.widget = QtGui.QDialog(parent) widget.setWindowModality(Qt.WindowModal) widget.setWindowTitle(N_('Shortcuts')) web = QtWebKit.QWebView(parent) web.setHtml(html) layout = qtutils.hbox(defs.no_margin, defs.spacing, web) widget.setLayout(layout) widget.resize(800, min(parent.height(), 600)) qtutils.add_action(widget, N_('Close'), widget.accept, hotkeys.QUESTION, *hotkeys.ACCEPT) widget.show() return widget
def add(self): widget = AddRemoteWidget(self) if not widget.add_remote(): return name = widget.name.value() url = widget.url.value() status, out = git.remote("add", name, url, with_status=True, with_stderr=True) if status != 0: qtutils.critical(N_('Error creating remote "%s"') % name, out) self.refresh()
def add(self): widget = AddRemoteWidget(self) if not widget.add_remote(): return name = widget.name.value() url = widget.url.value() status, out, err = git.remote('add', name, url) if status != 0: qtutils.critical( N_('Error creating remote "%s"') % name, out + err) self.refresh()
def add(self): widget = AddRemoteWidget(self) if not widget.add_remote(): return name = widget.name.value() url = widget.url.value() status, out, err = git.remote('add', name, url) if status != 0: qtutils.critical(N_('Error creating remote "%s"') % name, out + err) self.refresh()
def add(self): widget = AddRemoteWidget(self) if not widget.add_remote(): return name = widget.name.value() url = widget.url.value() status, out = git.remote('add', name, url, with_status=True, with_stderr=True) if status != 0: qtutils.critical('Error creating remote "%s"' % name, out) self.refresh()
def add_bookmark(self): path, ok = qtutils.prompt(N_('Path to git repository'), title=N_('Enter Git Repository'), text=core.getcwd()) if not ok: return normpath = utils.expandpath(path) if git.is_git_worktree(normpath): self.settings.add_bookmark(normpath) self.settings.save() self.refresh() else: qtutils.critical(N_('Error'), N_('%s is not a Git repository.') % path)
def delete(self): remote = qtutils.selected_item(self.remotes, self.remote_list) if remote is None: return title = N_("Delete Remote") question = N_("Delete remote?") info = N_('Delete remote "%s"') % remote ok_btn = N_("Delete") if not qtutils.confirm(title, question, info, ok_btn): return status, out = git.remote("rm", remote, with_status=True, with_stderr=True) if status != 0: qtutils.critical(N_('Error deleting remote "%s"') % remote, out) cola.model().update_status() self.refresh()
def diff_branch(): """Launches a diff against a branch.""" branch = choose_from_combo('Select Branch, Tag, or Commit-ish', ['HEAD^'] + cola.model().all_branches() + cola.model().tags) if not branch: return files = gitcmds.diff_filenames(branch) if not files: qtutils.critical('No Differences', 'No differences found for "%s"' % branch) return filename = BrowseDialog.select_file_from_list(files) if not filename: return cola.notifier().broadcast(signals.branch_mode, branch, filename)
def delete(self): remote = qtutils.selected_item(self.remotes, self.remote_list) if remote is None: return title = N_('Delete Remote') question = N_('Delete remote?') info = N_('Delete remote "%s"') % remote ok_btn = N_('Delete') if not qtutils.confirm(title, question, info, ok_btn): return status, out, err = git.remote('rm', remote) if status != 0: qtutils.critical( N_('Error deleting remote "%s"') % remote, out + err) main.model().update_status() self.refresh()
def delete(self): remote = qtutils.selected_item(self.remotes, self.remote_list) if remote is None: return title = N_('Delete Remote') question = N_('Delete remote?') info = N_('Delete remote "%s"') % remote ok_btn = N_('Delete') if not qtutils.confirm(title, question, info, ok_btn): return status, out, err = git.remote('rm', remote) if status != 0: qtutils.critical(N_('Error deleting remote "%s"') % remote, out + err) main.model().update_status() self.refresh()
def thread_done(self, results): self.setEnabled(True) self.progress.close() QtGui.QApplication.restoreOverrideCursor() detail_lines = [] for (cmd, status, out) in results: if status != 0: qtutils.critical( 'Create Branch Error', '"git %s" returned exit status "%d"' % (cmd, status)) return line = '"git %s" returned exit status %d' % (cmd, status) detail_lines.append(line) detail_lines.append(out) detail_lines.append('') details = '\n'.join(detail_lines) qtutils.information('Create Branch', 'Branch created', details=details) self.accept()
def delete(self): remote = qtutils.selected_item(self.remotes, self.remote_list) if remote is None: return title = 'Delete Remote' question = 'Delete remote?' info = unicode(self.tr('Delete remote "%s"')) % remote ok_btn = 'Delete' if not qtutils.confirm(title, question, info, ok_btn): return status, out = git.remote('rm', remote, with_status=True, with_stderr=True) if status != 0: qtutils.critical('Error deleting remote "%s"' % remote, out) cola.model().update_status() self.refresh()
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.names: qtutils.critical("Oops!", 'A stash named "%s" already exists' % stash_name) return keep_index = self.keep_index.isChecked() self.emit(SIGNAL(save_stash), stash_name, keep_index) self.accept() self.emit(SIGNAL(rescan))
def thread_done(self, results): self.setEnabled(True) self.progress.close() QtGui.QApplication.restoreOverrideCursor() detail_lines = [] for (cmd, status, out) in results: if status != 0: qtutils.critical('Create Branch Error', '"git %s" returned exit status "%d"' % (cmd, status)) return line = '"git %s" returned exit status %d' % (cmd, status) detail_lines.append(line) detail_lines.append(out) detail_lines.append('') details = '\n'.join(detail_lines) qtutils.information('Create Branch', 'Branch created', details=details) self.accept()
def show_shortcuts(): try: from PyQt4 import QtWebKit except ImportError: # redhat disabled QtWebKit in their qt build but don't punish the # users qtutils.critical(N_('This PyQt4 does not include QtWebKit.\n' 'The keyboard shortcuts feature is unavailable.')) return try: html = show_shortcuts.html except AttributeError: hotkeys = resources.doc(N_('hotkeys.html')) html = show_shortcuts.html = utils.slurp(hotkeys) try: widget = show_shortcuts.widget except AttributeError: parent = qtutils.active_window() widget = show_shortcuts.widget = QtGui.QDialog(parent) widget.setWindowModality(Qt.WindowModal) web = QtWebKit.QWebView(parent) web.setHtml(html) layout = QtGui.QHBoxLayout() layout.setMargin(0) layout.setSpacing(0) layout.addWidget(web) widget.setWindowTitle(N_('Shortcuts')) widget.setLayout(layout) widget.resize(800, min(parent.height(), 600)) qtutils.add_action(widget, N_('Close'), widget.accept, Qt.Key_Question, Qt.Key_Enter, Qt.Key_Return) widget.show() return widget
def create_branch(self): """Creates a branch; called by the "Create Branch" button""" self.getopts() revision = self.opts.revision branch = self.opts.branch no_update = self.no_update_radio.isChecked() ffwd_only = self.ffwd_only_radio.isChecked() existing_branches = gitcmds.branch_list() check_branch = False if not branch or not revision: qtutils.critical(N_('Missing Data'), N_('Please provide both a branch ' 'name and revision expression.')) return if branch in existing_branches: if no_update: msg = N_('Branch "%s" already exists.') % branch qtutils.critical(N_('Branch Exists'), msg) return # Whether we should prompt the user for lost commits commits = gitcmds.rev_list_range(revision, branch) check_branch = bool(commits) if check_branch: msg = (N_('Resetting "%(branch)s" to "%(revision)s" ' 'will lose commits.') % dict(branch=branch, revision=revision)) if ffwd_only: qtutils.critical(N_('Branch Exists'), msg) return lines = [msg] for idx, commit in enumerate(commits): subject = commit[1][0:min(len(commit[1]),16)] if len(subject) < len(commit[1]): subject += '...' lines.append('\t' + commit[0][:8] +'\t' + subject) if idx >= 5: skip = len(commits) - 5 lines.append('\t(%s)' % (N_('%d skipped') % skip)) break line = N_('Recovering lost commits may not be easy.') lines.append(line) if not qtutils.confirm(N_('Reset Branch?'), '\n'.join(lines), (N_('Reset "%(branch)s" to "%(revision)s"?') % dict(branch=branch, revision=revision)), N_('Reset Branch'), default=False, icon=qtutils.theme_icon('edit-undo.svg')): return self.setEnabled(False) self.progress.setEnabled(True) QtGui.QApplication.setOverrideCursor(Qt.WaitCursor) # Show a nice progress bar self.progress.setLabelText(N_('Updating...')) self.progress.show() self.thread.start()
def new_repo(): """Prompt for a new directory and create a new Git repository :returns str: repository path or None if no repository was created. """ dlg = QtGui.QFileDialog() dlg.setFileMode(QtGui.QFileDialog.Directory) dlg.setOption(QtGui.QFileDialog.ShowDirsOnly) dlg.show() dlg.raise_() if dlg.exec_() != QtGui.QFileDialog.Accepted: return None paths = dlg.selectedFiles() if not paths: return None path = ustr(paths[0]) if not path: return None # Avoid needlessly calling `git init`. if git.is_git_dir(path): # We could prompt here and confirm that they really didn't # mean to open an existing repository, but I think # treating it like an "Open" is a sensible DWIM answer. return path status, out, err = core.run_command(['git', 'init', path]) if status == 0: return path else: title = N_('Error Creating Repository') msg = (N_('"%(command)s" returned exit status %(status)d') % dict(command='git init %s' % path, status=status)) details = N_('Output:\n%s') % out if err: details += '\n\n' details += N_('Errors: %s') % err qtutils.critical(title, msg, details) return None
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(N_('Save Stash'), N_('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.names: qtutils.critical(N_('Error: Stash exists'), N_('A stash named "%s" already exists') % stash_name) return keep_index = self.keep_index.isChecked() cmds.do(SaveStash, stash_name, keep_index) self.accept() cmds.do(cmds.Rescan)
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.names: qtutils.critical('Oops!', 'A stash named "%s" already exists' % stash_name) return keep_index = self.keep_index.isChecked() cmds.do(SaveStash, stash_name, keep_index) self.accept() cmds.do(cmds.Rescan)
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: qtutils.critical(N_('Missing Revision'), N_('Please specify a revision to tag.')) return elif not tag_name: qtutils.critical(N_('Missing Name'), N_('Please specify a name for the new tag.')) return elif (sign_tag and not tag_msg and not qtutils.confirm(N_('Missing Tag Message'), N_('Tag-signing was requested but the tag ' 'message is empty.'), N_('An unsigned, lightweight tag will be ' 'created instead.\n' 'Create an unsigned tag?'), N_('Create Unsigned Tag'), default=False, icon=icons.save())): return status, output, err = cmds.do(cmds.Tag, tag_name, revision, sign=sign_tag, message=tag_msg) if status == 0: qtutils.information(N_('Tag Created'), N_('Created a new tag named "%s"') % tag_name, details=tag_msg or None) self.close() else: qtutils.critical( N_('Error: could not create tag "%s"') % tag_name, (N_('git tag returned exit code %s') % status) + ((output + err) and ('\n\n' + output + err) or ''))
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(N_('Missing Revision'), N_('Please specify a revision to tag.')) return elif not tag_name: critical(N_('Missing Name'), N_('Please specify a name for the new tag.')) return elif (sign_tag and not tag_msg and not qtutils.confirm(N_('Missing Tag Message'), N_('Tag-signing was requested but the tag ' 'message is empty.'), N_('An unsigned, lightweight tag will be ' 'created instead.\n' 'Create an unsigned tag?'), N_('Create Unsigned Tag'), default=False, icon=qtutils.save_icon())): return status, output, err = cmds.do(cmds.Tag, tag_name, revision, sign=sign_tag, message=tag_msg) if status == 0: information(N_('Tag Created'), N_('Created a new tag named "%s"') % tag_name, details=tag_msg or None) self.accept() else: critical(N_('Error: could not create tag "%s"') % tag_name, (N_('git tag returned exit code %s') % status) + ((output+err) and ('\n\n' + output + err) or ''))
def create_branch(self): """Creates a branch; called by the "Create Branch" button""" revision = self.model.revision branch = self.model.local_branch existing_branches = self.model.local_branches if not branch or not revision: qtutils.critical('Missing Data', 'Please provide both a branch ' 'name and revision expression.') return check_branch = False if branch in existing_branches: if self.view.no_update_radio.isChecked(): msg = self.tr("Branch '%s' already exists.") msg = unicode(msg) % branch qtutils.critical('Branch Exists', msg) return # Whether we should prompt the user for lost commits commits = gitcmds.rev_list_range(revision, branch) check_branch = bool(commits) if check_branch: msg = self.tr("Resetting '%s' to '%s' will " "lose the following commits:") lines = [ unicode(msg) % (branch, revision) ] for idx, commit in enumerate(commits): subject = commit[1][0:min(len(commit[1]),16)] if len(subject) < len(commit[1]): subject += '...' lines.append('\t' + commit[0][:8] +'\t' + subject) if idx >= 5: skip = len(commits) - 5 lines.append('\t(%d skipped)' % skip) break lines.extend([ unicode(self.tr('Recovering lost commits may not be easy.')), ]) if not qtutils.confirm('Reset Branch?', '\n'.join(lines), 'Reset "%s" to "%s"?' % (branch, revision), 'Reset Branch', default=False, icon=qtutils.icon('undo.svg')): return # TODO handle fetch track = self.view.remote_radio.isChecked() fetch = self.view.fetch_checkbox.isChecked() ffwd = self.view.ffwd_only_radio.isChecked() reset = self.view.reset_radio.isChecked() chkout = self.view.checkout_checkbox.isChecked() status, output = self.model.create_branch(branch, revision, track=track) qtutils.log(status, output) if status == 0 and chkout: status, output = self.model.git.checkout(branch, with_status=True, with_stderr=True) qtutils.log(status, output) self.view.accept()