Ejemplo n.º 1
0
    def importClicked(self):
        if self.repo is None:
            self.repo = repository.repos[self.repoCombo.currentIndex()]
        if self.layer is None:
            text = self.layerCombo.currentText()
            self.layer = resolveLayer(text)

        user, email = config.getUserInfo()
        if user is None:
            self.close()
            return
        message = self.messageBox.toPlainText()

        branch = self.branchCombo.currentText()
        try:
            self.repo.importgeopkg(self.layer, branch, message, user, email, False)
            filename, layername = namesFromLayer(self.layer)
            self.repo.checkoutlayer(filename, layername, ref = branch)
            self.layer.reload()
            self.layer.triggerRepaint()
        except GeoGigException as e:
            iface.messageBar().pushMessage("Error", str(e),
                                           level=QgsMessageBar.CRITICAL,
                                           duration=5)
            self.close()
            return

        addTrackedLayer(self.layer, self.repo.url)

        self.ok = True
        iface.messageBar().pushMessage("Layer was correctly added to repository",
                                       level=QgsMessageBar.INFO,
                                       duration=5)
        self.close()
 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 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 revertChange(layer):
    if hasLocalChanges(layer):
        QMessageBox.warning(config.iface.mainWindow(), 'Cannot revert commit',
                "The layer has local changes.\n"
                "Revert local changes before reverting a previous commit.",
                QMessageBox.Ok)
        return
    tracking = getTrackingInfo(layer)
    repo = Repository(tracking.repoUrl)
    filename, layername = namesFromLayer(layer)
    from geogig.gui.dialogs.historyviewer import HistoryViewerDialog
    dlg = HistoryViewerDialog(repo, layername)
    dlg.exec_()
    if dlg.ref is not None:
        #TODO check that selected commit is in history line

        commit = Commit.fromref(repo, dlg.ref)
        # check if we are reverting commit which adds layer to the repo
        if commit.addsLayer():
            QMessageBox.warning(config.iface.mainWindow(), 'Cannot revert commit',
                    "Commits which add layer to the repository can not "
                    "be reverted. Use GeoGig Navigator to remove layer "
                    "from branch.")
            return

        applyLayerChanges(repo, layer, commit.commitid, commit.parent.commitid, False)
        layer.reload()
        layer.triggerRepaint()
        config.iface.messageBar().pushMessage("GeoGig", "Commit changes have been reverted in local layer",
                                                      level=QgsMessageBar.INFO,
                                                      duration=5)
        commitdialog.suggestedMessage = "Reverted changes from commit %s [%s] " % (commit.commitid, commit.message)
Ejemplo n.º 5
0
def updateFeatureIds(repo, layer, featureIds):
    filename, layername = namesFromLayer(layer)
    con = sqlite3.connect(filename)
    cursor = con.cursor()
    for ids in featureIds:
        cursor.execute('INSERT INTO "%s_fids" VALUES ("%s", "%s")' %
                       (layername, ids[0], ids[1]))
    cursor.close()
    con.commit()
    con.close()
Ejemplo n.º 6
0
def getCommitId(layer):
    filename, layername = namesFromLayer(layer)
    con = sqlite3.connect(filename)
    cursor = con.cursor()
    cursor.execute(
        "SELECT commit_id FROM geogig_audited_tables WHERE table_name='%s';" %
        layername)
    commitid = cursor.fetchone()[0]
    cursor.close()
    con.close()
    return commitid
    def importClicked(self):

        ret = QMessageBox.warning(
            config.iface.mainWindow(), 'Import warning',
            "Importing a layer will modify the original layer and might cause data loss.\n"
            "Make sure you have a backup copy of your layer before importing.\n"
            "Do you want to import the selected layer?",
            QMessageBox.Yes | QMessageBox.No)
        if ret == QMessageBox.No:
            return

        if self.repo is None:
            self.repo = repository.repos[self.repoCombo.currentIndex()]
        if self.layer is None:
            text = self.layerCombo.currentText()
            self.layer = layerFromName(text)

        user, email = config.getUserInfo()
        if user is None:
            self.close()
            return
        message = self.messageBox.toPlainText() or datetime.now().strftime(
            "%Y-%m-%d %H_%M_%S")
        branch = self.branchCombo.currentText()
        try:
            self.repo.importgeopkg(self.layer, branch, message, user, email,
                                   False)
            filename, layername = namesFromLayer(self.layer)
            self.repo.checkoutlayer(filename, layername, ref=branch)
            self.layer.reload()
            self.layer.triggerRepaint()
        except GeoGigException as e:
            iface.messageBar().pushMessage("Error",
                                           str(e),
                                           level=QgsMessageBar.CRITICAL,
                                           duration=5)
            self.close()
            return

        addTrackedLayer(self.layer, self.repo.url)

        self.ok = True
        iface.messageBar().pushMessage(
            "Layer was correctly added to repository",
            level=QgsMessageBar.INFO,
            duration=5)
        self.close()
def addLayer(layer):
    if not layer.source().lower().split("|")[0].split(".")[-1] in [
            "geopkg", "gpkg"
    ]:
        QMessageBox.warning(
            config.iface.mainWindow(), 'Cannot import layer',
            "Only geopackage layers are supported at the moment",
            QMessageBox.Ok)
        return

    filename, layername = namesFromLayer(layer)
    l = QgsVectorLayer(filename, 'tmp', 'ogr')
    # only single-layer per file are supported
    spatialLayers = 0
    subLayers = l.dataProvider().subLayers()
    if len(subLayers) > 0:
        for lay in subLayers:
            tokens = lay.split(':')
            if len(tokens) > 4:
                tokens[1] += ":{}".format(tokens[2])
                del tokens[2]
            elif len(tokens) == 4:
                if tokens[3] != "None":
                    spatialLayers += 1
            else:
                continue

        if spatialLayers > 1:
            QMessageBox.warning(
                config.iface.mainWindow(), 'Cannot import layer',
                "Only geopackage layers with single sublayer are supported at the moment",
                QMessageBox.Ok)
            return

    repos = repository.repos
    if repos:
        dlg = ImportDialog(config.iface.mainWindow(), layer=layer)
        dlg.exec_()
        if dlg.ok:
            setAsRepoLayer(layer)
            repoWatcher.repoChanged.emit(dlg.repo)

    else:
        QMessageBox.warning(config.iface.mainWindow(), 'Cannot import layer',
                            "No repositories were found", QMessageBox.Ok)
    def importClicked(self):

        ret = QMessageBox.warning(config.iface.mainWindow(), 'Import warning',
                "Importing a layer will modify the original layer and might cause data loss.\n"
                "Make sure you have a backup copy of your layer before importing.\n"
                "Do you want to import the selected layer?",
                QMessageBox.Yes | QMessageBox.No)
        if ret == QMessageBox.No:
            return


        if self.repo is None:
            self.repo = repository.repos[self.repoCombo.currentIndex()]
        if self.layer is None:
            text = self.layerCombo.currentText()
            self.layer = layerFromName(text)

        user, email = config.getUserInfo()
        if user is None:
            self.close()
            return
        message = self.messageBox.toPlainText() or datetime.now().strftime("%Y-%m-%d %H_%M_%S")
        branch = self.branchCombo.currentText()
        try:
            self.repo.importgeopkg(self.layer, branch, message, user, email, False)
            filename, layername = namesFromLayer(self.layer)
            self.repo.checkoutlayer(filename, layername, ref = branch)
            self.layer.reload()
            self.layer.triggerRepaint()
        except GeoGigException as e:
            iface.messageBar().pushMessage("Error", str(e),
                                           level=QgsMessageBar.CRITICAL,
                                           duration=5)
            self.close()
            return

        addTrackedLayer(self.layer, self.repo.url)

        self.ok = True
        iface.messageBar().pushMessage("Layer was correctly added to repository",
                                       level=QgsMessageBar.INFO,
                                       duration=5)
        self.close()
def addLayer(layer):
    if not layer.source().lower().split("|")[0].split(".")[-1] in ["geopkg", "gpkg"]:
        QMessageBox.warning(config.iface.mainWindow(), 'Cannot import layer',
                "Only geopackage layers are supported at the moment",
                QMessageBox.Ok)
        return

    filename, layername = namesFromLayer(layer)
    l = QgsVectorLayer(filename, 'tmp', 'ogr')
    # only single-layer per file are supported
    spatialLayers = 0
    subLayers = l.dataProvider().subLayers()
    if len(subLayers) > 0:
        for lay in subLayers:
            tokens = lay.split(':')
            if len(tokens) > 4:
                tokens[1] += ":{}".format(tokens[2])
                del tokens[2]
            elif len(tokens) == 4:
                if tokens[3] != "None":
                    spatialLayers += 1
            else:
                continue

        if spatialLayers > 1:
            QMessageBox.warning(config.iface.mainWindow(), 'Cannot import layer',
                    "Only geopackage layers with single sublayer are supported at the moment",
                    QMessageBox.Ok)
            return

    repos = repository.repos
    if repos:
        dlg = ImportDialog(config.iface.mainWindow(), layer = layer)
        dlg.exec_()
        if dlg.ok:
            setAsRepoLayer(layer)
            repoWatcher.repoChanged.emit(dlg.repo)

    else:
        QMessageBox.warning(config.iface.mainWindow(), 'Cannot import layer',
                "No repositories were found",
                QMessageBox.Ok)
Ejemplo n.º 11
0
def revertChange(layer):
    tracking = getTrackingInfo(layer)
    repo = Repository(tracking.repoUrl)
    currentCommitId = getCommitId(layer)
    filename, layername = namesFromLayer(layer)
    dlg = CommitSelectDialog(repo, currentCommitId, layername)
    dlg.exec_()
    if dlg.ref is not None:
        #TODO check that selected commit is in history line
        applyLayerChanges(repo, layer, dlg.ref.commitid,
                          dlg.ref.parent.commitid, False)
        layer.reload()
        layer.triggerRepaint()
        config.iface.messageBar().pushMessage(
            "GeoGig",
            "Version changes have been reverted in local layer",
            level=QgsMessageBar.INFO,
            duration=5)
        commitdialog.suggestedMessage = "Reverted changes from version %s [%s] " % (
            dlg.ref.commitid, dlg.ref.message)
def revertChange(layer):
    if hasLocalChanges(layer):
        QMessageBox.warning(
            config.iface.mainWindow(), 'Cannot revert commit',
            "The layer has local changes.\n"
            "Revert local changes before reverting a previous commit.",
            QMessageBox.Ok)
        return
    tracking = getTrackingInfo(layer)
    repo = Repository(tracking.repoUrl)
    filename, layername = namesFromLayer(layer)
    from geogig.gui.dialogs.historyviewer import HistoryViewerDialog
    dlg = HistoryViewerDialog(repo, layername)
    dlg.exec_()
    if dlg.ref is not None:
        #TODO check that selected commit is in history line

        commit = Commit.fromref(repo, dlg.ref)
        # check if we are reverting commit which adds layer to the repo
        if commit.addsLayer():
            QMessageBox.warning(
                config.iface.mainWindow(), 'Cannot revert commit',
                "Commits which add layer to the repository can not "
                "be reverted. Use GeoGig Navigator to remove layer "
                "from branch.")
            return

        applyLayerChanges(repo, layer, commit.commitid, commit.parent.commitid,
                          False)
        layer.reload()
        layer.triggerRepaint()
        config.iface.messageBar().pushMessage(
            "GeoGig",
            "Commit changes have been reverted in local layer",
            level=QgsMessageBar.INFO,
            duration=5)
        commitdialog.suggestedMessage = "Reverted changes from commit %s [%s] " % (
            commit.commitid, commit.message)
Ejemplo n.º 13
0
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)
Ejemplo n.º 14
0
def checkoutLayer(repo, layername, bbox, ref=None):
    ref = ref or repo.HEAD
    newCommitId = repo.revparse(ref)
    trackedlayer = getTrackingInfoForGeogigLayer(repo.url, layername)
    if trackedlayer is not None:
        if not os.path.exists(trackedlayer.geopkg):
            removeTrackedLayer(trackedlayer.source)
            trackedlayer = None
            filename = layerGeopackageFilename(layername, repo.title,
                                               repo.group)
            source = "%s|layername=%s" % (filename, layername)
        else:
            source = trackedlayer.source
    else:
        filename = layerGeopackageFilename(layername, repo.title, repo.group)
        source = "%s|layername=%s" % (filename, layername)

    if trackedlayer is None:
        repo.checkoutlayer(filename, layername, bbox, ref or repo.HEAD)
        addTrackedLayer(source, repo.url)
        try:
            layer = resolveLayerFromSource(source)
            iface.messageBar().pushMessage(
                "GeoGig",
                "Layer was already included in the current QGIS project",
                level=QgsMessageBar.INFO,
                duration=5)
        except WrongLayerSourceException:
            layer = loadLayerNoCrsDialog(source, layername, "ogr")
            QgsMapLayerRegistry.instance().addMapLayers([layer])
            iface.messageBar().pushMessage("GeoGig",
                                           "Layer correctly added to project",
                                           level=QgsMessageBar.INFO,
                                           duration=5)
    elif ref is not None:
        currentCommitId = getCommitId(source)
        try:
            layer = resolveLayerFromSource(source)
            wasLoaded = True
        except WrongLayerSourceException:
            layer = loadLayerNoCrsDialog(source, layername, "ogr")
            wasLoaded = False

        if newCommitId != currentCommitId:
            if hasLocalChanges(layer):
                raise HasLocalChangesError()
            filename, layername = namesFromLayer(layer)
            repo.checkoutlayer(filename, layername, bbox, ref)
            layer.reload()
            if not wasLoaded:
                QgsMapLayerRegistry.instance().addMapLayers([layer])
                iface.messageBar().pushMessage(
                    "GeoGig",
                    "Layer correctly added to project",
                    level=QgsMessageBar.INFO,
                    duration=5)
            else:
                iface.messageBar().pushMessage(
                    "GeoGig",
                    "Layer correctly updated to specified version",
                    level=QgsMessageBar.INFO,
                    duration=5)
                layer.triggerRepaint()
        else:
            if wasLoaded:
                iface.messageBar().pushMessage(
                    "GeoGig",
                    "Layer was already included in the current QGIS project",
                    level=QgsMessageBar.INFO,
                    duration=5)
            else:
                QgsMapLayerRegistry.instance().addMapLayers([layer])
                iface.messageBar().pushMessage(
                    "GeoGig",
                    "Layer correctly added to the current QGIS project",
                    level=QgsMessageBar.INFO,
                    duration=5)

    repoWatcher.repoChanged.emit(repo)
    return layer
Ejemplo n.º 15
0
def applyLayerChanges(repo,
                      layer,
                      beforeCommitId,
                      afterCommitId,
                      clearAudit=True):
    layer.reload()
    filename, layername = namesFromLayer(layer)
    changesFilename = tempFilename("gpkg")
    beforeCommitId, afterCommitId = repo.revparse(
        beforeCommitId), repo.revparse(afterCommitId)
    repo.exportdiff(layername, beforeCommitId, afterCommitId, changesFilename)

    con = sqlite3.connect(filename)
    cursor = con.cursor()
    changesCon = sqlite3.connect(changesFilename)
    changesCursor = changesCon.cursor()

    attributes = [
        v[1] for v in cursor.execute("PRAGMA table_info('%s');" % layername)
    ]
    attrnames = [a for a in attributes if a != "fid"]

    changesCursor.execute("SELECT * FROM %s_changes WHERE audit_op=2;" %
                          layername)
    modified = changesCursor.fetchall()
    for m in modified:
        geogigfid = m[0]
        changesGpkgfid = gpkgfidFromGeogigfid(changesCursor, layername,
                                              geogigfid)
        gpkgfid = gpkgfidFromGeogigfid(cursor, layername, geogigfid)
        changesCursor.execute("SELECT * FROM %s WHERE fid='%s';" %
                              (layername, changesGpkgfid))
        featureRow = changesCursor.fetchone()
        attrs = {
            attr: featureRow[attributes.index(attr)]
            for attr in attrnames
        }
        vals = ",".join(["%s=?" % k for k in list(attrs.keys())])
        cursor.execute(
            "UPDATE %s SET %s WHERE fid='%s'" % (layername, vals, gpkgfid),
            list(attrs.values()))

    changesCursor.execute("SELECT * FROM %s_changes WHERE audit_op=1;" %
                          layername)
    added = changesCursor.fetchall()
    for a in added:
        geogigfid = a[0]
        changesGpkgfid = gpkgfidFromGeogigfid(changesCursor, layername,
                                              geogigfid)
        changesCursor.execute("SELECT * FROM %s WHERE fid='%s';" %
                              (layername, changesGpkgfid))
        featureRow = changesCursor.fetchone()
        attrs = {
            attr: featureRow[attributes.index(attr)]
            for attr in attrnames
        }
        cols = ', '.join('"%s"' % col for col in list(attrs.keys()))
        vals = ', '.join('?' for val in list(attrs.values()))
        cursor.execute(
            'INSERT INTO "%s" (%s) VALUES (%s)' % (layername, cols, vals),
            list(attrs.values()))
        gpkgfid = cursor.lastrowid
        cursor.execute('INSERT INTO "%s_fids" VALUES ("%s", "%s")' %
                       (layername, gpkgfid, geogigfid))

    changesCursor.execute("SELECT * FROM %s_changes WHERE audit_op=3;" %
                          layername)
    removed = changesCursor.fetchall()
    for r in removed:
        geogigfid = r[0]
        gpkgfid = gpkgfidFromGeogigfid(cursor, layername, geogigfid)
        cursor.execute("DELETE FROM %s WHERE fid='%s'" % (layername, gpkgfid))

    changesCursor.close()
    changesCon.close()

    if clearAudit:
        cursor.execute("DELETE FROM %s_audit;" % layername)
        cursor.execute(
            "UPDATE geogig_audited_tables SET commit_id='%s' WHERE table_name='%s'"
            % (afterCommitId, layername))

    con.commit()
    cursor.close()
    con.close()
Ejemplo n.º 16
0
    def importgeopkg(self, layer, branch, message, authorName, authorEmail,
                     interchange):
        QApplication.setOverrideCursor(QCursor(Qt.WaitCursor))
        filename, layername = namesFromLayer(layer)
        r = requests.get(self.url + "beginTransaction",
                         params={"output_format": "json"})
        r.raise_for_status()
        transactionId = r.json()["response"]["Transaction"]["ID"]
        self._checkoutbranch(branch, transactionId)
        payload = {
            "authorEmail": authorEmail,
            "authorName": authorName,
            "message": message,
            'destPath': layername,
            "format": "gpkg",
            "transactionId": transactionId
        }
        # fix_print_with_import
        if interchange:
            payload["interchange"] = True
            filename = self.saveaudittables(filename, layername)
        files = {
            'fileUpload': (os.path.basename(filename), open(filename, 'rb'))
        }

        encoder = MultipartEncoder(files)
        total = float(encoder.len)

        def callback(m):
            done = int(100 * m.bytes_read / total)
            iface.mainWindow().statusBar().showMessage(
                "Transferring geopkg to GeoGig server [{}%]".format(done))

        monitor = MultipartEncoderMonitor(encoder, callback)
        r = requests.post(self.url + "import.json",
                          params=payload,
                          data=monitor,
                          headers={'Content-Type': monitor.content_type})
        self.__log(r.url, r.text, payload, "POST")
        r.raise_for_status()
        resp = r.json()
        taskId = resp["task"]["id"]
        checker = TaskChecker(self.rootUrl, taskId)
        loop = QEventLoop()
        checker.taskIsFinished.connect(loop.exit, Qt.QueuedConnection)
        checker.start()
        loop.exec_(flags=QEventLoop.ExcludeUserInputEvents)
        QApplication.restoreOverrideCursor()
        iface.mainWindow().statusBar().showMessage("")
        if not checker.ok and "error" in checker.response["task"]:
            errorMessage = checker.response["task"]["error"]["message"]
            raise GeoGigException("Cannot import layer: %s" % errorMessage)
        if interchange:
            try:
                nconflicts = checker.response["task"]["result"]["Merge"][
                    "conflicts"]
            except KeyError, e:
                nconflicts = 0
            if nconflicts:
                mergeCommitId = self.HEAD
                importCommitId = checker.response["task"]["result"]["import"][
                    "importCommit"]["id"]
                ancestor = checker.response["task"]["result"]["Merge"][
                    "ancestor"]
                remote = checker.response["task"]["result"]["Merge"]["ours"]
                try:
                    featureIds = checker.response["task"]["result"]["import"][
                        "NewFeatures"]["type"][0].get("ids", [])
                except:
                    featureIds = []
                con = sqlite3.connect(filename)
                cursor = con.cursor()
                geomField = cursor.execute(
                    "SELECT column_name FROM gpkg_geometry_columns WHERE table_name='%s';"
                    % layername).fetchone()[0]

                def _local(fid):
                    cursor.execute(
                        "SELECT gpkg_fid FROM %s_fids WHERE geogig_fid='%s';" %
                        (layername, fid))
                    gpkgfid = int(cursor.fetchone()[0])
                    request = QgsFeatureRequest()
                    request.setFilterFid(gpkgfid)
                    try:
                        feature = next(layer.getFeatures(request))
                    except:
                        return None

                    def _ensureNone(v):
                        if v == NULL:
                            return None
                        else:
                            return v

                    local = {
                        f.name(): _ensureNone(feature[f.name()])
                        for f in layer.pendingFields()
                    }
                    try:
                        local[geomField] = feature.geometry().exportToWkt()
                    except:
                        local[geomField] = None
                    return local

                conflicts = []
                conflictsResponse = _ensurelist(
                    checker.response["task"]["result"]["Merge"]["Feature"])
                for c in conflictsResponse:
                    if c["change"] == "CONFLICT":
                        remoteFeatureId = c["ourvalue"]
                        localFeatureId = c["theirvalue"]
                        localFeature = _local(c["id"].split("/")[-1])
                        conflicts.append(
                            ConflictDiff(self, c["id"], ancestor, remote,
                                         importCommitId, localFeature,
                                         localFeatureId, remoteFeatureId,
                                         transactionId))
                cursor.close()
                con.close()
            else:
                #self._checkoutbranch("master", transactionId)
                self.closeTransaction(transactionId)
                mergeCommitId = checker.response["task"]["result"][
                    "newCommit"]["id"]
                importCommitId = checker.response["task"]["result"][
                    "importCommit"]["id"]
                try:
                    featureIds = checker.response["task"]["result"][
                        "NewFeatures"]["type"][0].get("id", [])
                except:
                    featureIds = []
                conflicts = []
            featureIds = [(f["provided"], f["assigned"]) for f in featureIds]
            return mergeCommitId, importCommitId, conflicts, featureIds