def currentRemoteChanged(self): remote = self.remoteCombo.currentText() repo = Repository(self.remotes[remote]) #TODO handle case of remote not being available branches = repo.branches() self.branchesCombo.clear() self.branchesCombo.addItems(branches)
def currentRemoteChanged(self): self.branchCombo.clear() remote = self.remoteCombo.currentText() try: repo = Repository(self.remotes[remote]) branches = repo.branches() self.branchCombo.addItems(branches) except: QMessageBox.warning(self, "Wrong connection", "The selected remote connection is not available or not supported.\n" "Only http-based connections are supported") return
def currentRemoteChanged(self): self.branchCombo.clear() remote = self.remoteCombo.currentText() try: repo = Repository(self.remotes[remote]) branches = repo.branches() self.branchCombo.addItems(branches) except: QMessageBox.warning( self, "Wrong connection", "The selected remote connection is not available or not supported.\n" "Only http-based connections are supported") return
def _createMultilayerTestRepo(modifiesRepo=True): conf.update([(k, os.getenv(k)) for k in conf if k in os.environ]) if modifiesRepo: repo = createRepoAtUrl(conf['REPOS_SERVER_URL'], "test", "severallayers_%s" % str(time.time())) else: global multilayerTestRepo if multilayerTestRepo is not None: return multilayerTestRepo try: multilayerTestRepo = createRepoAtUrl(conf['REPOS_SERVER_URL'], "test", "original_severallayers") except GeoGigException: multilayerTestRepo = Repository( conf['REPOS_SERVER_URL'] + "repos/original_severallayers/", "test", "original_severallayers") return multilayerTestRepo repo = multilayerTestRepo _importLayerToRepo(repo, "first") _importLayerToRepo(repo, "second") _importLayerToRepo(repo, "third") _importLayerToRepo(repo, "lines") repo.createbranch(repo.HEAD, "mybranch") global _lastRepo _lastRepo = repo return _lastRepo
def localChanges(self, layer): filename, layername = namesFromLayer(layer) con = sqlite3.connect(filename) cursor = con.cursor() attributes = [v[1] for v in cursor.execute("PRAGMA table_info('%s');" % layername)] attrnames = [a for a in attributes if a != "fid"] cursor.execute("SELECT * FROM %s_audit;" % layername) changes = cursor.fetchall() changesdict = {} tracking = getTrackingInfo(layer) repo = Repository(tracking.repoUrl) commitid = cursor.execute("SELECT commit_id FROM geogig_audited_tables WHERE table_name='%s';" % layername).fetchone()[0] geomField = cursor.execute("SELECT column_name FROM gpkg_geometry_columns WHERE table_name='%s';" % layername).fetchone()[0] for c in changes: featurechanges = {} path = str(c[attributes.index("fid")]) for attr in attrnames: if c[-1] == LOCAL_FEATURE_REMOVED: value = None else: if attr != geomField: value = c[attributes.index(attr)] else: request = QgsFeatureRequest().setFilterExpression("fid=%s" % path) features = list(layer.getFeatures(request)) if len(features) == 0: continue value = features[0].geometry().exportToWkt().upper() featurechanges[attr] = value path = geogigFidFromGpkgFid(tracking, path) changesdict[path] = LocalDiff(layername, path, repo, featurechanges, commitid, c[-1]) return changesdict
def _createSimpleTestRepo(modifiesRepo=True, group=None, name=None): conf.update([(k, os.getenv(k)) for k in conf if k in os.environ]) if modifiesRepo: repo = createRepoAtUrl(conf['REPOS_SERVER_URL'], group or "test", name or "simple_%s" % str(time.time())) else: global simpleTestRepo if simpleTestRepo is not None: return simpleTestRepo try: simpleTestRepo = createRepoAtUrl(conf['REPOS_SERVER_URL'], group or "test", name or "original_simple") except GeoGigException: simpleTestRepo = Repository( conf['REPOS_SERVER_URL'] + "repos/original_simple/", group or "test", name or "original_simple") return simpleTestRepo repo = simpleTestRepo _importLayerToRepo(repo, "first") log = repo.log() filename = tempFilename("gpkg") repo.checkoutlayer(filename, "points", ref=log[0].commitid) layer = loadLayerNoCrsDialog(filename, "points", "ogr") with edit(layer): feat = QgsFeature() feat.setGeometry(QgsGeometry.fromPoint(QgsPoint(10, 10))) feat.setAttributes([3, 2]) layer.addFeatures([feat]) repo.importgeopkg(layer, "master", "second", "tester", "*****@*****.**", True) log = repo.log() filename = tempFilename("gpkg") repo.checkoutlayer(filename, "points", ref=log[0].commitid) layer = loadLayerNoCrsDialog(filename, "points", "ogr") features = list(layer.getFeatures()) for feature in features: pt = feature.geometry().asPoint() if pt.x() == 10 and pt.y() == 10: featureid = feature.id() break with edit(layer): layer.changeGeometry(featureid, QgsGeometry.fromPoint(QgsPoint(5, 5))) repo.importgeopkg(layer, "master", "third", "tester", "*****@*****.**", True) repo.createbranch(repo.HEAD, "mybranch") repo.createtag(repo.HEAD, "mytag") global _lastRepo _lastRepo = repo return _lastRepo
def _createWithMergeTestRepo(modifiesRepo=True): conf.update([(k, os.getenv(k)) for k in conf if k in os.environ]) if modifiesRepo: repo = createRepoAtUrl(conf['REPOS_SERVER_URL'], "test", "withmerge_%s" % str(time.time())) else: global withMergeTestRepo if withMergeTestRepo is not None: return withMergeTestRepo try: withMergeTestRepo = createRepoAtUrl(conf['REPOS_SERVER_URL'], "test", "original_withmerge") except GeoGigException: withMergeTestRepo = Repository( conf['REPOS_SERVER_URL'] + "repos/original_withmerge/", "test", "original_withmerge") return withMergeTestRepo repo = withMergeTestRepo _importLayerToRepo(repo, "first") repo.createbranch(repo.HEAD, "mybranch") filename = tempFilename("gpkg") repo.checkoutlayer(filename, "points", ref=repo.HEAD) layer = loadLayerNoCrsDialog(filename, "points", "ogr") with edit(layer): feat = QgsFeature() feat.setGeometry(QgsGeometry.fromPoint(QgsPoint(10, 10))) feat.setAttributes([3, 2]) layer.addFeatures([feat]) repo.importgeopkg(layer, "mybranch", "second", "tester", "*****@*****.**", True) filename = tempFilename("gpkg") repo.checkoutlayer(filename, "points", ref=repo.HEAD) layer = loadLayerNoCrsDialog(filename, "points", "ogr") with edit(layer): feat = QgsFeature() feat.setGeometry(QgsGeometry.fromPoint(QgsPoint(9, 9))) feat.setAttributes([9, 9]) layer.addFeatures([feat]) repo.importgeopkg(layer, "master", "second", "tester", "*****@*****.**", True) repo.merge("mybranch", "master") global _lastRepo _lastRepo = repo return _lastRepo
def _createEmptyTestRepo(modifiesRepo = False): conf.update([(k, os.getenv(k)) for k in conf if k in os.environ]) if modifiesRepo: repo = createRepoAtUrl(conf['REPOS_SERVER_URL'], "test", "empty_%s" % str(time.time())) else: global emptyTestRepo if emptyTestRepo is not None: return emptyTestRepo try: emptyTestRepo = createRepoAtUrl(conf['REPOS_SERVER_URL'], "test", "original_empty") except GeoGigException: emptyTestRepo = Repository(conf['REPOS_SERVER_URL'] + "repos/original_empty/", "test", "original_empty") return emptyTestRepo repo = emptyTestRepo global _lastRepo _lastRepo = repo return _lastRepo
def canvasPressEvent(self, e): layer = config.iface.activeLayer() if layer is None or not isinstance(layer, QgsVectorLayer): config.iface.messageBar().pushMessage("No layer selected or the current active layer is not a valid vector layer", level = QgsMessageBar.WARNING, duration = 5) return if not layertracking.isRepoLayer(layer): config.iface.messageBar().pushMessage("The current active layer is not being tracked as part of a GeoGig repo", level = QgsMessageBar.WARNING, duration = 5) return trackedlayer = layertracking.getTrackingInfo(layer) point = self.toMapCoordinates(e.pos()) searchRadius = self.canvas().extent().width() * .01; r = QgsRectangle() r.setXMinimum(point.x() - searchRadius); r.setXMaximum(point.x() + searchRadius); r.setYMinimum(point.y() - searchRadius); r.setYMaximum(point.y() + searchRadius); r = self.toLayerCoordinates(layer, r); fit = layer.getFeatures(QgsFeatureRequest().setFilterRect(r).setFlags(QgsFeatureRequest.ExactIntersect)); fid = None try: feature = next(fit) fid = feature.id() fid = geogigFidFromGpkgFid(trackedlayer, fid) if fid is None: return except StopIteration as e: return repo = Repository(trackedlayer.repoUrl) menu = QMenu() versionsAction = QAction("Show all versions of this feature...", None) versionsAction.triggered.connect(lambda: self.versions(repo, trackedlayer.layername, fid)) menu.addAction(versionsAction) blameAction = QAction("Show authorship...", None) blameAction.triggered.connect(lambda: self.blame(repo, trackedlayer.layername, fid)) menu.addAction(blameAction) point = config.iface.mapCanvas().mapToGlobal(e.pos()) menu.exec_(point)
def syncLayer(layer): tracking = getTrackingInfo(layer) repo = Repository(tracking.repoUrl) filename, layername = namesFromLayer(layer) con = sqlite3.connect(filename) cursor = con.cursor() cursor.execute("SELECT * FROM %s_audit;" % layername) changes = bool(cursor.fetchall()) cursor.close() con.close() if changes: con = sqlite3.connect(filename) cursor = con.cursor() beforeAttrs = set(v[1] for v in cursor.execute("PRAGMA table_info('%s');" % layername)) afterAttrs = set( v[1] for v in cursor.execute("PRAGMA table_info('%s_audit');" % layername) if v[1] not in ["audit_timestamp", "audit_op"]) cursor.close() con.close() if beforeAttrs != afterAttrs: ret = QMessageBox.warning( iface.mainWindow(), "Cannot commit changes to repository", "The structure of attributes table has been modified.\n" "This type of change is not supported by GeoGig.", QMessageBox.Yes) return user, email = config.getUserInfo() if user is None: return dlg = CommitDialog(repo, layername) dlg.exec_() if dlg.branch is None: return if dlg.branch not in repo.branches(): commitId = getCommitId(layer) repo.createbranch(commitId, dlg.branch) mergeCommitId, importCommitId, conflicts, featureIds = repo.importgeopkg( layer, dlg.branch, dlg.message, user, email, True) if conflicts: ret = QMessageBox.warning( iface.mainWindow(), "Error while syncing", "There are conflicts between local and remote changes.\n" "Do you want to continue and fix them?", QMessageBox.Yes | QMessageBox.No) if ret == QMessageBox.No: repo.closeTransaction(conflicts[0].transactionId) return solved, resolvedConflicts = solveConflicts(conflicts) if not solved: repo.closeTransaction(conflicts[0].transactionId) return for conflict, resolution in zip(conflicts, list(resolvedConflicts.values())): if resolution == ConflictDialog.LOCAL: conflict.resolveWithLocalVersion() elif resolution == ConflictDialog.REMOTE: conflict.resolveWithRemoteVersion() elif resolution == ConflictDialog.DELETE: conflict.resolveDeletingFeature() else: conflict.resolveWithNewFeature(resolution) repo.commitAndCloseMergeAndTransaction(user, email, "Resolved merge conflicts", conflicts[0].transactionId) updateFeatureIds(repo, layer, featureIds) try: applyLayerChanges(repo, layer, importCommitId, mergeCommitId) except: QgsMessageLog.logMessage( "Database locked while syncing. Using full layer checkout instead", level=QgsMessageLog.CRITICAL) repo.checkoutlayer(tracking.geopkg, layername, None, mergeCommitId) commitdialog.suggestedMessage = "" else: branches = [] for branch in repo.branches(): trees = repo.trees(branch) if layername in trees: branches.append(branch) branch, ok = QInputDialog.getItem(iface.mainWindow(), "Sync", "Select branch to update from", branches, 0, False) if not ok: return commitId = getCommitId(layer) headCommitId = repo.revparse(branch) applyLayerChanges(repo, layer, commitId, headCommitId) layer.reload() layer.triggerRepaint() repoWatcher.repoChanged.emit(repo) iface.messageBar().pushMessage("GeoGig", "Layer has been correctly synchronized", level=QgsMessageBar.INFO, duration=5) repoWatcher.layerUpdated.emit(layer)