Ejemplo n.º 1
0
 def _do_gp(self, path):
     self._logger.info("Pulling git repository: %s", path)
     gitHandler = GitHandler(self._logger)
     retCode, _pOut, pErr = gitHandler.pull(path)
     if retCode != 0:
         if pErr:
             self._logger.error(u"Error pulling git repository. Stderr: %s", pErr.decode("utf-8"))
         else:
             self._logger.error("Error pulling git repository.")
Ejemplo n.º 2
0
 def __init__(self, parent, logger):
     super(AddRepoDialog, self).__init__(parent)
     self.logger = logger
     self._canAutoUpdate = False
     self._closeable = True
     self._path = None
     self._gitHandler = GitHandler(logger)
Ejemplo n.º 3
0
 def _checkAllRepositories(self):
     from PyQt4.QtCore import Qt
     from plugin_repositories.plugin_repositories_gui import PluginRepositoriesGUI
     model = self._ui.getTable().model()
     outdated = set()
     upToDate = {}
     gh = GitHandler(self.logger)
     for row in xrange(model.rowCount()):
         path = convert_string(model.item(row, PluginRepositoriesGUI.PATH_COLUMN).data(Qt.DisplayRole).toString())
         if gh.hasGit(path):
             needsPull, reason = gh.needsPull(True, path)
             if needsPull:
                 outdated.add(path)
             else:
                 upToDate[path] = reason
     return outdated, upToDate
Ejemplo n.º 4
0
class GitUpdateHandler(AppUpdateHandler):
    """Used if Lunchinator is run directly from git."""
    
    def __init__(self, logger):
        super(GitUpdateHandler, self).__init__(logger)
        self._gitHandler = GitHandler(logger)
        
    @classmethod
    def appliesToConfiguration(cls, logger):
        gh = GitHandler(logger)
        return gh.hasGit()
    
    def activate(self):
        AppUpdateHandler.activate(self)
        if self.canCheckForUpdate():
            self.checkForUpdate()
        
    def _getInitialStatus(self):
        return "Not checked."
        
    def getInstalledVersion(self):
        return get_settings().get_commit_count()
        
    def canCheckForUpdate(self):
        return lunchinator_has_gui()
    
    @loggingFunc
    def checkForUpdate(self):
        self._setStatus("Checking for update...")
        from lunchinator.callables import AsyncCall
        AsyncCall(getValidQtParent(),
                  self.logger,
                  self._gitHandler.needsPull,
                  self._checkUpdateSuccess,
                  self._checkUpdateError)(returnReason=True)
        
    @loggingFunc
    def _checkUpdateSuccess(self, tup):
        needsPull, reason = tup
        if needsPull:
            self._setStatus("Repository can be updated to version %s." % self._gitHandler.getRemoteCommitCount())
            self._installReady()
        else:
            self._setStatus(u"No update: " + reason)
            
    @loggingFunc
    def _checkUpdateError(self, msg=None):
        st = u"Checking for update failed"
        if msg:
            st += u": " + msg
        self._setStatus(st, True)
        
    def prepareInstallation(self, commands):
        commands.addGitPull(get_settings().get_main_package_path())
Ejemplo n.º 5
0
 def get_version(self):
     if self._version == None:
         try:
             version_file = self.get_resource("version")
             with contextlib.closing(open(version_file, "r")) as vfh:
                 self._version = vfh.read().strip()
             self._commit_count = self._version.split(".")[-1]
         except Exception:
             from lunchinator.git import GitHandler
             gh = GitHandler(getCoreLogger())
             if gh.hasGit():
                 commit_count = gh.getCommitCount()
                 if commit_count:
                     self._commit_count = commit_count
                     self._version = commit_count
             else:
                 getCoreLogger().error("Error reading/parsing version file")
                 self._version = u"unknown.unknown"
                 self._commit_count = "unknown"
             
     return self._version
    def __init__(self, logger, parent):
        super(PluginRepositoriesGUI, self).__init__(parent)
       
        self.logger = logger
        self._gitHandler = GitHandler(logger)
        
        layout = QVBoxLayout(self)
        
        self._reposTable = QTreeView(self) 
        self._reposTable.setIndentation(0)
        self._reposTable.header().setStretchLastSection(False)
                
        self._reposModel = QStandardItemModel(self._reposTable)
        self._initModel()
        self._reposTable.setModel(self._reposModel)
        
        self._reposTable.setSelectionMode(QTreeView.ExtendedSelection)
        self._reposTable.selectionModel().selectionChanged.connect(self._selectionChanged)
        
        layout.addWidget(self._reposTable)

        buttonLayout = QHBoxLayout()    
        addButton = QPushButton("Add...")
        addButton.clicked.connect(self.addRepository)
        self._removeButton = QPushButton("Remove")
        self._removeButton.setEnabled(False)
        self._removeButton.clicked.connect(self._removeSelected)
        refreshButton = QPushButton("Check Status")
        refreshButton.clicked.connect(self.checkForUpdates)
        buttonLayout.addWidget(addButton)
        buttonLayout.addWidget(self._removeButton)
        buttonLayout.addWidget(refreshButton)
        
        layout.addLayout(buttonLayout)
        
        self._statusWidget = QWidget(self) 
        self._statusWidget.setVisible(False)
        statusLayout = QHBoxLayout(self._statusWidget)
        statusLayout.setContentsMargins(0, 0, 0, 0)
        self._statusLabel = QLabel(self)
        statusLayout.addWidget(self._statusLabel)
        layout.addWidget(self._statusWidget)
Ejemplo n.º 7
0
class AddRepoDialog(ErrorMessageDialog):
    _WORKING_COPY = 0
    _CLONE_URL = 1
    
    def __init__(self, parent, logger):
        super(AddRepoDialog, self).__init__(parent)
        self.logger = logger
        self._canAutoUpdate = False
        self._closeable = True
        self._path = None
        self._gitHandler = GitHandler(logger)
        
    def _createPathPage(self):
        try:
            from PyQt4.QtGui import QCommonStyle
            style = QCommonStyle()
        except:
            style = None
        
        w = QWidget(self)
        layout = QVBoxLayout(w)
        
        inputWidget = QWidget(self)
        inputLayout = QHBoxLayout(inputWidget)
        inputLayout.setContentsMargins(0, 0, 0, 0)
        
        inputLayout.addWidget(QLabel("Path:", self))
        self._pathEdit = QLineEdit(self)
        if hasattr(self._pathEdit, "setPlaceholderText"):
            self._pathEdit.setPlaceholderText(u"Directory Path")
        inputLayout.addWidget(self._pathEdit, 1)
        
        browseButton = QPushButton(self)
        browseButton.setAutoDefault(False)
        if style != None:
            browseIcon = style.standardIcon(QStyle.SP_DirOpenIcon)
        else:
            browseIcon = None
        
        if browseIcon and not browseIcon.isNull():
            browseButton.setIcon(browseIcon)
        else:
            browseButton.setText("Browse...")
        browseButton.clicked.connect(self._browse)
        inputLayout.addWidget(browseButton, 0, Qt.AlignHCenter)
        
        layout.addWidget(inputWidget, 0)        
        return w, layout
    
    def _createURLPage(self):
        w = QWidget(self)
        layout = QVBoxLayout(w)
        
        inputWidget = QWidget(self)
        inputLayout = QHBoxLayout(inputWidget)
        inputLayout.setContentsMargins(0, 0, 0, 0)
        
        inputLayout.addWidget(QLabel("URL:", self))
        self._urlEdit = QLineEdit(self)
        if hasattr(self._urlEdit, "setPlaceholderText"):
            self._urlEdit.setPlaceholderText(u"Git URL (HTTPS/SSH)")
        inputLayout.addWidget(self._urlEdit, 1)
        
        layout.addWidget(inputWidget, 0)        
        return w, layout
        
    def _addPropertyWidgets(self, layout, autoUpdateEnabled):
        propertiesLayout = QHBoxLayout()
        propertiesLayout.setContentsMargins(0, 0, 0, 0)
        
        activeCheckBox = QCheckBox("Active", self)
        activeCheckBox.setChecked(True)
        propertiesLayout.addWidget(activeCheckBox)
        self._activeBoxes.append(activeCheckBox)
        
        autoUpdateCheckBox = QCheckBox("Auto Update", self)
        autoUpdateCheckBox.setEnabled(autoUpdateEnabled)
        propertiesLayout.addWidget(autoUpdateCheckBox, 1, Qt.AlignLeft)
        self._autoUpdateBoxes.append(autoUpdateCheckBox)
        
        layout.addLayout(propertiesLayout)
        
    def _initInputUI(self, dialogLayout):
        self.setWindowTitle(u"Add Plugin Repository")

        self._tabs = QTabWidget(self)
        
        self._activeBoxes = []
        self._autoUpdateBoxes = []

        w, layout = self._createPathPage()
        self._addPropertyWidgets(layout, False)
        self._tabs.addTab(w, "Working Copy")
        
        w, layout = self._createURLPage()
        self._addPropertyWidgets(layout, True)
        self._tabs.addTab(w, "Clone URL")
        
        dialogLayout.addWidget(self._tabs)
                
    def _autoUpdateChanged(self, newState):
        self._autoUpdate = newState == Qt.Checked
        
    @loggingSlot()
    def _browse(self):
        fd = QFileDialog(self)
        fd.setOptions(QFileDialog.ShowDirsOnly)
        fd.setFileMode(QFileDialog.Directory)
        fd.exec_()
        if fd.result() == QDialog.Accepted:
            path = fd.selectedFiles()[0]
            self._setPath(path)
        
    def _checkPath(self):
        self._canAutoUpdate = self._gitHandler.hasGit(self.getPath())
        
        box = self._autoUpdateBoxes[self._WORKING_COPY]
        if not self._canAutoUpdate:
            box.setChecked(False)
        if box.isEnabled() != self._canAutoUpdate: 
            box.setEnabled(self._canAutoUpdate)
            return True
        return False
            
    def _setPath(self, path):
        self._pathEdit.setText(path)
        self._checkPath()
    
    def getPath(self):
        if self._path is not None:
            return self._path
        return convert_string(self._pathEdit.text())
    
    def isRepositoryActive(self):
        return self._activeBoxes[self._tabs.currentIndex()].checkState() == Qt.Checked
    
    def isAutoUpdateEnabled(self):
        return self._autoUpdateBoxes[self._tabs.currentIndex()].checkState() == Qt.Checked
    
    def canAutoUpdate(self):
        return self._tabs.currentIndex() == self._CLONE_URL or self._canAutoUpdate
    
    def _setWorking(self, w):
        self._closeable = not w
        self._tabs.setEnabled(not w)
        self._setButtonsEnabled(not w)
    
    @loggingSlot()
    def _checkOK(self):
        if self._tabs.currentIndex() == self._WORKING_COPY:
            if not os.path.isdir(self.getPath()):
                self._error("The given path does not exist or is not a directory.")
            elif not self._checkPath():
                # no change to properties widget -> accept
                self._path = self.getPath()
                self.accept()
        else:
            self._info(u"Cloning repository...")
            self._setWorking(True)
            url = convert_string(self._urlEdit.text())
            AsyncCall(self, self.logger, self._checkAndClone, self._cloneSuccess, self._cloneError)(url)

    def closeEvent(self, event):
        if self._closeable:
            event.accept()
        else:
            event.ignore()

    def _checkAndClone(self, url):
        if not self._gitHandler.isGitURL(url):
            raise ValueError(u"The given URL does not exist or is no Git repository.")

        targetDir = get_settings().get_config(self._gitHandler.extractRepositoryNameFromURL(url))
        targetDir = getUniquePath(targetDir)
        self._gitHandler.clone(url, targetDir)
        return targetDir
        
    @loggingSlot(object)
    def _cloneSuccess(self, path):
        self._setWorking(False)
        self.setResult(self.Accepted)
        self._path = path
        self.close()
        
    @loggingSlot(object)
    def _cloneError(self, msg):
        self._setWorking(False)
        self._error(msg)
class PluginRepositoriesGUI(QWidget):
    PATH_COLUMN = 1
    ACTIVE_COLUMN = 0
    AUTO_UPDATE_COLUMN = 2
    STATUS_COLUMN = 3
    
    addRepository = pyqtSignal()
    checkForUpdates = pyqtSignal()
    
    def __init__(self, logger, parent):
        super(PluginRepositoriesGUI, self).__init__(parent)
       
        self.logger = logger
        self._gitHandler = GitHandler(logger)
        
        layout = QVBoxLayout(self)
        
        self._reposTable = QTreeView(self) 
        self._reposTable.setIndentation(0)
        self._reposTable.header().setStretchLastSection(False)
                
        self._reposModel = QStandardItemModel(self._reposTable)
        self._initModel()
        self._reposTable.setModel(self._reposModel)
        
        self._reposTable.setSelectionMode(QTreeView.ExtendedSelection)
        self._reposTable.selectionModel().selectionChanged.connect(self._selectionChanged)
        
        layout.addWidget(self._reposTable)

        buttonLayout = QHBoxLayout()    
        addButton = QPushButton("Add...")
        addButton.clicked.connect(self.addRepository)
        self._removeButton = QPushButton("Remove")
        self._removeButton.setEnabled(False)
        self._removeButton.clicked.connect(self._removeSelected)
        refreshButton = QPushButton("Check Status")
        refreshButton.clicked.connect(self.checkForUpdates)
        buttonLayout.addWidget(addButton)
        buttonLayout.addWidget(self._removeButton)
        buttonLayout.addWidget(refreshButton)
        
        layout.addLayout(buttonLayout)
        
        self._statusWidget = QWidget(self) 
        self._statusWidget.setVisible(False)
        statusLayout = QHBoxLayout(self._statusWidget)
        statusLayout.setContentsMargins(0, 0, 0, 0)
        self._statusLabel = QLabel(self)
        statusLayout.addWidget(self._statusLabel)
        layout.addWidget(self._statusWidget)
        
    def clear(self):
        self._initModel()
        
    def _updateStatusItem(self, item, path, outdated=None, upToDate=None):
        # first check fresh results, then the ones from repositories
        if upToDate and path in upToDate:
            item.setText(upToDate[path])
            if upToDate[path] == GitHandler.UP_TO_DATE_REASON:
                item.setData(QColor(0, 255, 0), Qt.DecorationRole)
            else:
                item.setData(QColor(255, 0, 0), Qt.DecorationRole)
        elif outdated and path in outdated:
            item.setText("Repository can be updated")
            item.setData(QColor(255, 215, 0), Qt.DecorationRole)
        elif get_settings().get_plugin_repositories().isUpToDate(path):
            item.setText("No updates (for details, check status)")
            item.setData(QColor(0, 255, 0), Qt.DecorationRole)
        elif get_settings().get_plugin_repositories().isOutdated(path):
            item.setText("Repository can be updated")
            item.setData(QColor(255, 215, 0), Qt.DecorationRole)
        else:
            item.setData(None, Qt.DecorationRole)
        
    def updateStatusItems(self, outdated=None, upToDate=None):
        for row in xrange(self._reposModel.rowCount()):
            path = convert_string(self._reposModel.item(row, self.PATH_COLUMN).data(Qt.DisplayRole).toString())
            self._updateStatusItem(self._reposModel.item(row, self.STATUS_COLUMN), path, outdated, upToDate)
        
    def _initModel(self):
        from PyQt4.QtCore import QStringList
        self._reposModel.clear()
        stringList = QStringList([u"Active", u"Path", u"Auto Update", u"Status"])
        self._reposModel.setColumnCount(stringList.count())
        self._reposModel.setHorizontalHeaderLabels(stringList)
        
    def appendRepository(self, path, active, autoUpdate, canAutoUpdate = None):
        activeItem = QStandardItem()
        activeItem.setEditable(False)
        activeItem.setCheckState(Qt.Checked if active else Qt.Unchecked)
        activeItem.setCheckable(True)
        
        pathItem = QStandardItem()
        pathItem.setData(path, Qt.DisplayRole)
        pathItem.setEditable(False)
        
        autoUpdateItem = QStandardItem()
        autoUpdateItem.setEditable(False)
        if canAutoUpdate == None:
            canAutoUpdate = self._gitHandler.hasGit(path)
        if canAutoUpdate:
            autoUpdateItem.setCheckState(Qt.Checked if autoUpdate else Qt.Unchecked)
            autoUpdateItem.setCheckable(True)
                
        statusItem = QStandardItem()
        self._updateStatusItem(statusItem, path)
                
        self._reposModel.appendRow([activeItem, pathItem, autoUpdateItem, statusItem])
        
    def resizeColumns(self):
        self._reposTable.resizeColumnToContents(self.ACTIVE_COLUMN)
        self._reposTable.resizeColumnToContents(self.AUTO_UPDATE_COLUMN)
        self._reposTable.header().setResizeMode(self.PATH_COLUMN, QHeaderView.Stretch)
        self._reposTable.header().setResizeMode(self.STATUS_COLUMN, QHeaderView.ResizeToContents)
    
    def getTable(self):
        return self._reposTable
    
    @loggingSlot(QItemSelection, QItemSelection)
    def _selectionChanged(self, _sel, _desel):
        selection = self._reposTable.selectionModel().selectedRows()
        self._removeButton.setEnabled(len(selection) > 0)
        
    @loggingSlot()
    def _removeSelected(self):
        selection = self._reposTable.selectionModel().selectedRows()
        for index in selection:
            self._reposTable.model().removeRow(index.row())
        
    def setStatus(self, msg, _progress=False):
        if msg:
            self._statusLabel.setText(msg)
            self._statusWidget.setVisible(True)
        else:
            self._statusWidget.setVisible(False)
Ejemplo n.º 9
0
 def __init__(self, logger):
     super(GitUpdateHandler, self).__init__(logger)
     self._gitHandler = GitHandler(logger)
Ejemplo n.º 10
0
 def appliesToConfiguration(cls, logger):
     gh = GitHandler(logger)
     return gh.hasGit()