Esempio n. 1
0
    def test_sticky(self):
        s = struct.Set()
        # create sticky contianer on two stores
        with s.create("foo", [self.store1, self.store2]) as dummy:
            # create document on first store
            with Connector().create("test.format.foo", "test.ignore",
                                    [self.store1]) as w:
                w.commit()
                doc = w.getDoc()
                rev = w.getRev()

                watch1 = self.watchDoc(doc, connector.Watch.EVENT_REPLICATED)
                watch2 = self.watchRev(rev, connector.Watch.EVENT_REPLICATED)

                # add to sticky container
                s['dummy'] = struct.DocLink(doc)
                s.save()

            # wait for sticky replicatin to happen
            self.assertTrue(watch1.waitForWatch())
            self.assertTrue(watch2.waitForWatch())

            # check doc (with rev) to exist on all stores
            l = Connector().lookup_doc(doc)
            self.assertEqual(l.revs(), [rev])
            self.assertEqual(len(l.stores(rev)), 2)
            self.assertTrue(self.store1 in l.stores(rev))
            self.assertTrue(self.store2 in l.stores(rev))

            l = Connector().lookup_rev(rev)
            self.assertEqual(len(l), 2)
            self.assertTrue(self.store1 in l)
            self.assertTrue(self.store2 in l)
Esempio n. 2
0
    def test_sync_merge(self):
        (doc, rev1,
         rev2) = self.createMerge("org.hotchpotch.dict",
                                  {'HPSD': struct.dumps({"a": 1})},
                                  {'HPSD': struct.dumps({
                                      "a": 1,
                                      "b": 2
                                  })},
                                  {'HPSD': struct.dumps({
                                      "a": 1,
                                      "c": 3
                                  })})
        l = self.performSync(doc, 'merge')

        rev = l.revs()[0]
        s = Connector().stat(rev)
        self.assertEqual(len(s.parents()), 2)
        self.assertTrue(rev1 in s.parents())
        self.assertTrue(rev2 in s.parents())

        # all revs on all stores?
        l = Connector().lookup_rev(rev1)
        self.assertTrue(self.store1 in l)
        self.assertTrue(self.store2 in l)
        l = Connector().lookup_rev(rev2)
        self.assertTrue(self.store1 in l)
        self.assertTrue(self.store2 in l)

        # see if merge was ok
        with Connector().peek(rev) as r:
            hpsd = struct.loads(r.readAll('HPSD'))
            self.assertEqual(hpsd, {"a": 1, "b": 2, "c": 3})
Esempio n. 3
0
 def tearDown(self):
     CommonParts.tearDown(self)
     # make sure stores are unmounted to kill sync
     if Connector().enum().isMounted(STORE1):
         Connector().unmount(STORE1)
     if Connector().enum().isMounted(STORE2):
         Connector().unmount(STORE2)
Esempio n. 4
0
 def setUp(self):
     # make sure stores are unmounted to kill sync
     if Connector().enum().isMounted(STORE1):
         Connector().unmount(STORE1)
     if Connector().enum().isMounted(STORE2):
         Connector().unmount(STORE2)
     CommonParts.setUp(self)
Esempio n. 5
0
    def assertRevContent(self, rev, content):
        with Connector().peek(rev) as r:
            for (part, data) in content.items():
                revData = r.readAll(part)
                self.assertEqual(revData, data)

        s = Connector().stat(rev)
        for part in s.parts():
            self.assertTrue(part in content)
Esempio n. 6
0
 def __doCreate(self, sourceRev):
     info = Connector().stat(sourceRev)
     destStores = Connector().lookup_rev(self.rev())
     with Connector().create(info.type(), info.creator(), destStores) as w:
         with Connector().peek(sourceRev) as r:
             for part in info.parts():
                 w.write(part, r.readAll(part))
         w.commit()
         destDoc = w.getDoc()
         # add link
         self.model().insertLink(struct.DocLink(destDoc))
         # save immediately
         self.save()
Esempio n. 7
0
 def __addCreateActions(self, menu):
     newMenu = menu.addMenu(QtGui.QIcon("icons/filenew.png"),
                            "New document")
     sysStore = struct.Container(
         struct.DocLink(Connector().enum().sysStore()))
     templatesDict = struct.Container(sysStore.get("templates:"))
     items = templatesDict.items()
     items.sort(key=lambda item: item[0])
     for (name, link) in items:
         rev = link.rev()
         icon = QtGui.QIcon(Registry().getIcon(
             Connector().stat(rev).type()))
         action = newMenu.addAction(icon, name)
         action.triggered.connect(lambda x, r=rev: self.__doCreate(r))
Esempio n. 8
0
    def __init__(self, uuid, isDoc, parent=None):
        super(PropertiesDialog, self).__init__(parent)

        mainLayout = QtGui.QVBoxLayout()
        mainLayout.setSizeConstraint(QtGui.QLayout.SetFixedSize)

        if isDoc:
            self.doc = uuid
            info = Connector().lookup_doc(uuid)
            mainLayout.addWidget(DocumentTab(info.stores(), "document"))
            self.revs = info.revs()
        else:
            self.doc = None
            mainLayout.addWidget(
                DocumentTab(Connector().lookup_rev(uuid), "revision"))
            self.revs = [uuid]

        if len(self.revs) == 0:
            QtGui.QMessageBox.warning(
                self, 'Missing document',
                'The requested document was not found on any store.')
            sys.exit(1)

        tabWidget = QtGui.QTabWidget()
        self.annoTab = AnnotationTab(self.revs, isDoc
                                     and (len(self.revs) == 1))
        QtCore.QObject.connect(self.annoTab, QtCore.SIGNAL("changed()"),
                               self.__changed)
        tabWidget.addTab(self.annoTab, "Annotation")
        tabWidget.addTab(HistoryTab(self.revs), "History")
        if isDoc:
            tabWidget.addTab(RevisionTab(self.revs), "Revisions")
        else:
            tabWidget.addTab(RevisionTab(self.revs), "Revision")
        mainLayout.addWidget(tabWidget)

        if isDoc and (len(self.revs) == 1):
            self.buttonBox = QtGui.QDialogButtonBox(
                QtGui.QDialogButtonBox.Save | QtGui.QDialogButtonBox.Close)
            self.buttonBox.button(
                QtGui.QDialogButtonBox.Save).setEnabled(False)
            self.buttonBox.accepted.connect(self.__save)
            self.buttonBox.rejected.connect(self.reject)
        else:
            self.buttonBox = QtGui.QDialogButtonBox(QtGui.QDialogButtonBox.Ok)
            self.buttonBox.accepted.connect(self.accept)
        mainLayout.addWidget(self.buttonBox)
        self.setLayout(mainLayout)
        self.setWindowTitle("Properties of %s" % (self.annoTab.getTitle()))
Esempio n. 9
0
    def test_suspend_multi(self):
        c = Connector()
        (doc, rev1, rev_s1) = self.createSuspendDoc()

        with c.update(doc, rev1) as w:
            w.writeAll('FILE', 'forward')
            w.commit()
            rev2 = w.getRev()

        with c.update(doc, rev2) as w:
            w.writeAll('FILE', 'Hail to the king, baby!')
            w.suspend()
            rev_s2 = w.getRev()

        l = c.lookup_doc(doc)
        self.assertEqual(l.revs(), [rev2])
        self.assertEqual(len(l.preRevs()), 2)
        self.assertTrue(rev_s1 in l.preRevs())
        self.assertTrue(rev_s2 in l.preRevs())

        s = c.stat(rev_s1)
        self.assertEqual(s.parents(), [rev1])
        s = c.stat(rev_s2)
        self.assertEqual(s.parents(), [rev2])

        self.assertRevContent(rev1, {'FILE': 'ok'})
        self.assertRevContent(rev_s1, {'FILE': 'update'})
        self.assertRevContent(rev2, {'FILE': 'forward'})
        self.assertRevContent(rev_s2, {'FILE': 'Hail to the king, baby!'})
Esempio n. 10
0
    def test_merge(self):
        c = Connector()
        stores = [self.store1, self.store2]
        w = self.create("public.data", "test.ignore", stores)
        w.commit()
        doc = w.getDoc()
        rev = w.getRev()

        with c.update(doc, rev, stores=[self.store1]) as w:
            w.write('FILE', 'first')
            w.commit()
            rev1 = w.getRev()

        with c.update(doc, rev, stores=[self.store2]) as w:
            w.write('FILE', 'second')
            w.commit()
            rev2 = w.getRev()

        with c.update(doc, rev1, stores=stores) as w:
            w.setParents([rev1, rev2])
            w.commit()
            rev3 = w.getRev()

        self.assertTrue(c.sync(doc) == rev3)

        l = c.lookup_doc(doc)
        self.assertEqual(l.revs(), [rev3])

        self.assertEqual(set(c.lookup_rev(rev)), set(stores))
        self.assertEqual(set(c.lookup_rev(rev1)), set(stores))
        self.assertEqual(set(c.lookup_rev(rev2)), set(stores))
        self.assertEqual(set(c.lookup_rev(rev3)), set(stores))
Esempio n. 11
0
    def test_bad(self):
        c = Connector()
        stores = [self.store1, self.store2]
        w = self.create("public.data", "test.ignore", stores)
        w.commit()
        doc = w.getDoc()
        rev = w.getRev()

        with c.update(doc, rev, stores=[self.store1]) as w:
            w.write('FILE', 'first')
            w.commit()
            rev1 = w.getRev()

        with c.update(doc, rev, stores=[self.store2]) as w:
            w.write('FILE', 'second')
            w.commit()
            rev2 = w.getRev()

        self.failIfEqual(rev, rev1)
        self.failIfEqual(rev, rev2)
        self.failIfEqual(rev1, rev2)

        self.assertRaises(IOError, c.sync, doc)

        l = c.lookup_doc(doc)
        self.assertEqual(len(l.revs()), 2)
        self.assertEqual(l.rev(self.store1), rev1)
        self.assertEqual(l.rev(self.store2), rev2)
Esempio n. 12
0
    def docRead(self, readWrite, handle):
        stat = Connector().stat(self.rev())
        uti = stat.type()
        if readWrite:
            linkMap = None
        else:
            linkMap = stat.linkMap()
        if uti in DictModel.UTIs:
            model = DictModel(linkMap, self)
        elif uti in SetModel.UTIs:
            model = SetModel(linkMap, self)
        else:
            raise TypeError('Unhandled type code: %s' % (uti))

        self.__setModel(model)
        if self.__settings:
            self.__applySettings(self.__settings)

        model.rowsInserted.connect(self._emitSaveNeeded)
        model.rowsRemoved.connect(self._emitSaveNeeded)
        model.dataChanged.connect(self.__dataChanged)
        model.modelReset.connect(self.__dataChanged)
        model.modelReset.connect(lambda: self.selectionChanged.emit())
        self.listView.selectionModel().selectionChanged.connect(
            lambda: self.selectionChanged.emit())

        autoClean = self.metaDataGetField(CollectionModel.AUTOCLEAN, False)
        model.doLoad(handle, readWrite, autoClean)
        if model.hasChanged():
            self._emitSaveNeeded()
	def __update(self):
		if self.__seen:
			self.__unwatch()
			self.__available = len(Connector().lookup_rev(self.__rev)) > 0
		else:
			self.__available = False
			try:
				stat = Connector().stat(self.__rev)
				self.__mtime = stat.mtime()
				self.__seen = True
				self.__available = True
				self.__view._addParents(stat.parents())
				self.__unwatch()
			except IOError:
				self.__watch()
				return
Esempio n. 14
0
 def __addReplicateActions(self, menu, link):
     c = Connector()
     try:
         allVolumes = set(c.lookup_rev(self.rev()))
         if isinstance(link, struct.DocLink):
             lookup = c.lookup_doc(link.doc())
             curVolumes = set(lookup.stores())
             try:
                 for rev in lookup.revs():
                     curVolumes = curVolumes & set(
                         c.lookup_rev(rev, curVolumes))
             except IOError:
                 curVolumes = set()
         else:
             curVolumes = set(c.lookup_rev(link.rev()))
     except IOError:
         return
     repVolumes = allVolumes - curVolumes
     for store in repVolumes:
         try:
             rev = c.lookup_doc(store).rev(store)
             with c.peek(rev) as r:
                 metaData = struct.loads(r.readAll('META'))
                 try:
                     name = metaData["org.hotchpotch.annotation"]["title"]
                 except:
                     name = "Unknown store"
                 action = menu.addAction("Replicate item to '%s'" % name)
                 action.triggered.connect(
                     lambda x, l=link, s=store: self.__doReplicate(l, s))
         except:
             pass
Esempio n. 15
0
    def test_create(self):
        w = self.create("public.data", "test.foo", [self.store1])
        w.commit()
        doc = w.getDoc()
        rev = w.getRev()

        s = Connector().stat(rev)
        self.assertEqual(s.creator(), "test.foo")
Esempio n. 16
0
    def test_suspend(self):
        c = Connector()
        (doc, rev1, rev2) = self.createSuspendDoc()

        l = c.lookup_doc(doc)
        self.assertEqual(l.revs(), [rev1])
        self.assertEqual(l.preRevs(), [rev2])
        self.assertRevContent(rev1, {'FILE': 'ok'})
        self.assertRevContent(rev2, {'FILE': 'update'})
	def _extractMetaData(self):
		caption = self._view.metaDataGetField(DocumentView.HPA_TITLE, "Unnamed")
		if not self._view.doc() and self._view.rev():
			try:
				mtime = Connector().stat(self._view.rev()).mtime()
				caption = caption + " @ " + str(mtime)
			except IOError:
				pass
		self._main.setCaption(caption)
Esempio n. 18
0
    def __init__(self, revs, parent=None):
        super(HistoryTab, self).__init__(parent)

        # TODO: implement something nice gitk like...
        self.__historyList = []
        self.__historyRevs = []
        heads = revs[:]
        while len(heads) > 0:
            newHeads = []
            for rev in heads:
                try:
                    if rev not in self.__historyRevs:
                        stat = Connector().stat(rev)
                        mtime = str(stat.mtime())
                        comment = ""
                        if 'META' in stat.parts():
                            try:
                                with Connector().peek(rev) as r:
                                    metaData = struct.loads(r.readAll('META'))
                                    comment = extractMetaData(
                                        metaData, [
                                            "org.hotchpotch.annotation",
                                            "comment"
                                        ], "")
                            except IOError:
                                pass
                        self.__historyList.append(mtime + " - " + comment)
                        self.__historyRevs.append(rev)
                        newHeads.extend(stat.parents())
                except IOError:
                    pass
            heads = newHeads

        self.__historyListBox = QtGui.QListWidget()
        self.__historyListBox.setSizePolicy(QtGui.QSizePolicy.Ignored,
                                            QtGui.QSizePolicy.Ignored)
        self.__historyListBox.insertItems(0, self.__historyList)
        QtCore.QObject.connect(
            self.__historyListBox,
            QtCore.SIGNAL("itemDoubleClicked(QListWidgetItem *)"), self.__open)

        layout = QtGui.QVBoxLayout()
        layout.addWidget(self.__historyListBox)
        self.setLayout(layout)
Esempio n. 19
0
 def setAutoClean(self, autoClean):
     self.__autoClean = autoClean
     if autoClean and self.__mutable:
         removed = [x for x in self._listing if not x.isValid()]
         self._listing = [x for x in self._listing if x.isValid()]
         if len(removed) > 0:
             self.__changedContent = True
             for item in removed:
                 Connector().unwatch(item)
             self.reset()
Esempio n. 20
0
    def test_create(self):
        c = Connector()
        w = self.create("test.format", "test.ignore", [self.store1])
        self.assertEqual(w.getType(), "test.format")
        w.commit()
        doc = w.getDoc()
        rev = w.getRev()

        s = c.stat(rev)
        self.assertEqual(s.type(), "test.format")
Esempio n. 21
0
    def test_already_same(self):
        c = Connector()
        stores = [self.store1, self.store2]
        w = self.create("public.data", "test.ignore", stores)
        w.commit()
        doc = w.getDoc()
        rev = w.getRev()

        self.assertTrue(c.sync(doc) == rev)
        self.assertTrue(c.sync(doc, stores=stores) == rev)
Esempio n. 22
0
    def test_resume_wrong(self):
        c = Connector()
        (doc, rev1, rev2) = self.createSuspendDoc()
        self.assertRaises(IOError, c.resume, doc, rev1)

        l = c.lookup_doc(doc)
        self.assertEqual(l.revs(), [rev1])
        self.assertEqual(l.preRevs(), [rev2])
        self.assertRevContent(rev1, {'FILE': 'ok'})
        self.assertRevContent(rev2, {'FILE': 'update'})
Esempio n. 23
0
 def __save(self):
     rev = self.revs[0]
     self.buttonBox.button(QtGui.QDialogButtonBox.Save).setEnabled(False)
     with Connector().peek(rev) as r:
         metaData = struct.loads(r.readAll('META'))
     setMetaData(metaData, ["org.hotchpotch.annotation", "title"],
                 str(self.annoTab.titleEdit.text()))
     setMetaData(metaData, ["org.hotchpotch.annotation", "description"],
                 str(self.annoTab.descEdit.text()))
     if self.annoTab.tagsEdit.hasAcceptableInput():
         tagString = self.annoTab.tagsEdit.text()
         tagSet = set([tag.strip() for tag in str(tagString).split(',')])
         tagList = list(tagSet)
         setMetaData(metaData, ["org.hotchpotch.annotation", "tags"],
                     tagList)
     with Connector().update(self.doc, rev) as writer:
         writer.writeAll('META', struct.dumps(metaData))
         writer.commit()
         self.revs[0] = writer.getRev()
Esempio n. 24
0
    def __dropFile(self, data, onto):
        # FIXME: find a better way than calling back to the parent
        stores = Connector().lookup_rev(self.__parent.rev())
        urlList = data.urls()
        if onto.isValid():
            if len(urlList) != 1:
                choice = QtGui.QMessageBox.question(
                    self.__parent, "Overwrite",
                    "Cannot overwrite: more than one dragged file. Import instead?",
                    QtGui.QMessageBox.Yes | QtGui.QMessageBox.No,
                    QtGui.QMessageBox.No)
                if choice != QtGui.QMessageBox.Yes:
                    return False
            elif not os.path.isfile(str(urlList[0].toLocalFile().toUtf8())):
                choice = QtGui.QMessageBox.question(
                    self.__parent, "Overwrite",
                    "Cannot overwrite: dragged item is not a file. Import instead?",
                    QtGui.QMessageBox.Yes | QtGui.QMessageBox.No,
                    QtGui.QMessageBox.No)
                if choice != QtGui.QMessageBox.Yes:
                    return False
            else:
                choice = QtGui.QMessageBox.question(
                    self.__parent, "Overwrite",
                    "Do you want to overwrite the selected item? If not, the file will be imported as new item.",
                    QtGui.QMessageBox.Yes | QtGui.QMessageBox.No
                    | QtGui.QMessageBox.Cancel, QtGui.QMessageBox.No)

                if choice == QtGui.QMessageBox.Cancel:
                    return False
                elif choice == QtGui.QMessageBox.Yes:
                    link = self.getItemLinkUser(onto)
                    path = str(urlList[0].toLocalFile().toUtf8())
                    try:
                        return importer.overwriteFile(stores, link, path)
                    except IOError:
                        pass
                    except OSError:
                        pass
                    return False

        # import and add to container
        for url in urlList:
            try:
                path = str(url.toLocalFile().toUtf8())
                handle = importer.importFile(stores, path)
                if handle:
                    try:
                        self.insertLink(struct.DocLink(handle.getDoc()))
                        self.__parent.save()
                    finally:
                        handle.close()
            except IOError:
                pass
        return True
Esempio n. 25
0
 def removeRows(self, position, rows, parent):
     if not self.__mutable:
         return False
     self.__changedContent = True
     self.beginRemoveRows(QtCore.QModelIndex(), position,
                          position + rows - 1)
     for i in range(rows):
         Connector().unwatch(self._listing[position])
         del self._listing[position]
     self.endRemoveRows()
     return True
Esempio n. 26
0
    def test_readback(self):
        dataOrig = 'akjdfaqhfkjsalur\naqidahgajsoasoiga\n\nakhsfdlkaf\r\n'
        w = self.create("public.data", "test.foo", [self.store1])
        w.writeAll('FILE', dataOrig)
        w.commit()
        doc = w.getDoc()
        rev = w.getRev()

        with Connector().peek(rev) as r:
            dataRead = r.readAll('FILE')

        self.assertEqual(dataOrig, dataRead)
Esempio n. 27
0
    def test_sync_merge_fallback(self):
        (doc, rev1, rev2) = self.createMerge("public.data", {},
                                             {'FILE': "left"},
                                             {'FILE': "right"})
        l = self.performSync(doc, 'merge')

        rev = l.revs()[0]
        s = Connector().stat(rev)
        self.assertEqual(len(s.parents()), 2)
        self.assertTrue(rev1 in s.parents())
        self.assertTrue(rev2 in s.parents())
        self.assertRevContent(rev, {'FILE': 'left'})
Esempio n. 28
0
    def createMerge(self, type, base, left, right):
        w = self.create(type, "test.foo", [self.store1, self.store2])
        for (part, data) in base.items():
            w.writeAll(part, data)
        w.commit()
        doc = w.getDoc()
        rev1 = w.getRev()

        with Connector().update(doc, rev1, stores=[self.store1]) as w:
            for (part, data) in left.items():
                w.writeAll(part, data)
            w.commit()
            rev2 = w.getRev()

        with Connector().update(doc, rev1, stores=[self.store2]) as w:
            for (part, data) in right.items():
                w.writeAll(part, data)
            w.commit()
            rev3 = w.getRev()

        return (doc, rev2, rev3)
Esempio n. 29
0
    def createFastForward(self):
        w = self.create("public.data", "test.foo", [self.store1, self.store2])
        w.commit()
        doc = w.getDoc()
        rev1 = w.getRev()

        with Connector().update(doc, rev1, stores=[self.store1]) as w:
            w.writeAll('FILE', 'forward')
            w.commit()
            rev2 = w.getRev()

        return (doc, rev2)
Esempio n. 30
0
    def test_transitive_keep(self):
        with Connector().create("test.format.foo", "test.foo",
                                [self.store1]) as w1:
            with Connector().create("test.format.bar", "test.foo",
                                    [self.store1]) as w2:
                w2.write('FILE', 'test')
                w2.commit()
                doc2 = w2.getDoc()
                rev2 = w2.getRev()

                # create a reference from w1 to w2
                w1.write('HPSD', struct.dumps([struct.DocLink(doc2)]))
                w1.commit()
                doc1 = w1.getDoc()
                rev1 = w1.getRev()

            # w2 is closed now, w1 still open, should prevent gc
            self.gc(self.store1)

            l = Connector().lookup_doc(doc1)
            self.assertEqual(l.revs(), [rev1])
            self.assertEqual(l.preRevs(), [])
            self.assertEqual(Connector().lookup_rev(rev1), [self.store1])
            l = Connector().lookup_doc(doc2)
            self.assertEqual(l.revs(), [rev2])
            self.assertEqual(l.preRevs(), [])
            self.assertEqual(Connector().lookup_rev(rev2), [self.store1])