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 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})
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))
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)
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)
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)
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)
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")
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 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 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)
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'})
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)
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'})
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")
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'})
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'})
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()
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))
def createSuspendDoc(self): c = Connector() w = self.create("test.format", "test.ignore", [self.store1]) w.writeAll('FILE', 'ok') w.commit() doc = w.getDoc() rev1 = w.getRev() with c.update(doc, rev1) as w: w.writeAll('FILE', 'update') w.suspend() rev2 = w.getRev() return (doc, rev1, rev2)
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
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()))
def test_update_change(self): c = Connector() w = self.create("public.data", "test.foo", [self.store1]) w.commit() doc = w.getDoc() rev1 = w.getRev() with c.update(doc, rev1, "test.baz") as w: w.commit() rev2 = w.getRev() s = c.stat(rev1) self.assertEqual(s.creator(), "test.foo") s = c.stat(rev2) self.assertEqual(s.creator(), "test.baz")
def test_fork(self): c = Connector() w = self.create("public.data", "test.foo", [self.store1]) w.commit() doc1 = w.getDoc() rev1 = w.getRev() w = self.fork(rev1, "test.bar") w.commit() doc2 = w.getDoc() rev2 = w.getRev() s = c.stat(rev1) self.assertEqual(s.creator(), "test.foo") s = c.stat(rev2) self.assertEqual(s.creator(), "test.bar")
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
def performSync(self, doc, strategy): watch = self.watchDoc(doc, connector.Watch.EVENT_MODIFIED) self.startSync(strategy, self.store1, self.store2) while True: watch.reset() self.assertTrue(watch.waitForWatch()) l = Connector().lookup_doc(doc) if len(l.revs()) == 1: break self.assertEqual(len(l.stores()), 2) self.assertTrue(self.store1 in l.stores()) self.assertTrue(self.store2 in l.stores()) return l
def test_collect(self): c = Connector() # deliberately close handle after creating! with c.create("public.data", "test.foo", [self.store1]) as w: w.commit() doc = w.getDoc() rev = w.getRev() # perform a GC cycle self.gc(self.store1) l = c.lookup_doc(doc) self.assertEqual(l.revs(), []) self.assertEqual(l.preRevs(), []) self.assertRaises(IOError, c.stat, rev)
def test_sync_ff_err(self): (doc, rev1, rev2) = self.createMerge("public.data", {}, {'FILE' : "left"}, {'FILE' : "right"}) watch = self.watchDoc(doc, connector.Watch.EVENT_MODIFIED) self.startSync('ff', self.store1, self.store2) self.startSync('ff', self.store2, self.store1) self.assertFalse(watch.waitForWatch(1)) # check that doc is not synced l = Connector().lookup_doc(doc) self.assertEqual(len(l.revs()), 2) self.assertEqual(l.rev(self.store1), rev1) self.assertEqual(l.rev(self.store2), rev2)
def test_create_keep_handle(self): c = Connector() with c.create("public.data", "test.foo", [self.store1]) as w: w.commit() doc = w.getDoc() rev = w.getRev() # perform a GC cycle self.gc(self.store1) l = c.lookup_doc(doc) self.assertEqual(l.revs(), [rev]) self.assertEqual(l.preRevs(), []) c.stat(rev)
def update(self): # reset everything self.__valid = False self.__icon = None for i in xrange(len(self.__columnDefs)): column = self.__columnDefs[i] if column.derived(): self.__columnValues[i] = column.default() # determine revision needMerge = False if isinstance(self.__link, struct.DocLink): self.__link.update() revisions = self.__link.revs() if len(revisions) == 0: return elif len(revisions) > 1: needMerge = True # TODO: maybe sort by date rev = revisions[0] else: rev = self.__link.rev() self.__rev = rev # stat try: s = Connector().stat(rev) except IOError: return self.__uti = s.type() if needMerge: image = QtGui.QImage(Registry().getIcon(s.type())) painter = QtGui.QPainter() painter.begin(image) painter.drawImage(0, 0, QtGui.QImage("icons/uti/merge_overlay.png")) painter.end() self.__icon = QtGui.QIcon(QtGui.QPixmap.fromImage(image)) else: self.__icon = QtGui.QIcon(Registry().getIcon(s.type())) # overwritable by external files? self.__replacable = (not needMerge) and (not Registry().conformes( self.__uti, "org.hotchpotch.container")) self.__valid = True self.__updateColumns()
def test_resume_suspend_orig(self): c = Connector() (doc, rev1, rev2) = self.createSuspendDoc() with c.resume(doc, rev2) as w: w.suspend() rev3 = w.getRev() l = c.lookup_doc(doc) self.assertEqual(l.revs(), [rev1]) self.assertEqual(l.preRevs(), [rev3]) s = c.stat(rev3) self.assertEqual(s.parents(), [rev1]) self.assertRevContent(rev1, {'FILE' : 'ok'}) self.assertRevContent(rev3, {'FILE' : 'update'})
def test_resume_commit(self): c = Connector() (doc, rev1, rev2) = self.createSuspendDoc() with c.resume(doc, rev2) as w: w.writeAll('FILE', 'What are you waiting for, christmas?') w.commit() rev3 = w.getRev() l = c.lookup_doc(doc) self.assertEqual(l.revs(), [rev3]) self.assertEqual(len(l.preRevs()), 0) s = c.stat(rev3) self.assertEqual(s.parents(), [rev1]) self.assertRevContent(rev1, {'FILE' : 'ok'}) self.assertRevContent(rev3, {'FILE' : 'What are you waiting for, christmas?'})
def test_resume_suspend_orig(self): c = Connector() (doc, rev1, rev2) = self.createSuspendDoc() with c.resume(doc, rev2) as w: w.suspend() rev3 = w.getRev() l = c.lookup_doc(doc) self.assertEqual(l.revs(), [rev1]) self.assertEqual(l.preRevs(), [rev3]) s = c.stat(rev3) self.assertEqual(s.parents(), [rev1]) self.assertRevContent(rev1, {'FILE': 'ok'}) self.assertRevContent(rev3, {'FILE': 'update'})
def update(self): # reset everything self.__valid = False self.__icon = None for i in xrange(len(self.__columnDefs)): column = self.__columnDefs[i] if column.derived(): self.__columnValues[i] = column.default() # determine revision needMerge = False if isinstance(self.__link, struct.DocLink): self.__link.update() revisions = self.__link.revs() if len(revisions) == 0: return elif len(revisions) > 1: needMerge = True # TODO: maybe sort by date rev = revisions[0] else: rev = self.__link.rev() self.__rev = rev # stat try: s = Connector().stat(rev) except IOError: return self.__uti = s.type() if needMerge: image = QtGui.QImage(Registry().getIcon(s.type())) painter = QtGui.QPainter() painter.begin(image) painter.drawImage(0, 0, QtGui.QImage("icons/uti/merge_overlay.png")) painter.end() self.__icon = QtGui.QIcon(QtGui.QPixmap.fromImage(image)) else: self.__icon = QtGui.QIcon(Registry().getIcon(s.type())) # overwritable by external files? self.__replacable = (not needMerge) and ( not Registry().conformes(self.__uti, "org.hotchpotch.container")) self.__valid = True self.__updateColumns()
def test_sync_ff_err(self): (doc, rev1, rev2) = self.createMerge("public.data", {}, {'FILE': "left"}, {'FILE': "right"}) watch = self.watchDoc(doc, connector.Watch.EVENT_MODIFIED) self.startSync('ff', self.store1, self.store2) self.startSync('ff', self.store2, self.store1) self.assertFalse(watch.waitForWatch(1)) # check that doc is not synced l = Connector().lookup_doc(doc) self.assertEqual(len(l.revs()), 2) self.assertEqual(l.rev(self.store1), rev1) self.assertEqual(l.rev(self.store2), rev2)
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
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!'})
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})
def test_resume_abort(self): c = Connector() (doc, rev1, rev2) = self.createSuspendDoc() with c.resume(doc, rev2) as w: w.writeAll('FILE', 'Hail to the king, baby!') l = c.lookup_doc(doc) self.assertEqual(l.revs(), [rev1]) self.assertEqual(l.preRevs(), [rev2]) w.close() 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 test_resume_commit(self): c = Connector() (doc, rev1, rev2) = self.createSuspendDoc() with c.resume(doc, rev2) as w: w.writeAll('FILE', 'What are you waiting for, christmas?') w.commit() rev3 = w.getRev() l = c.lookup_doc(doc) self.assertEqual(l.revs(), [rev3]) self.assertEqual(len(l.preRevs()), 0) s = c.stat(rev3) self.assertEqual(s.parents(), [rev1]) self.assertRevContent(rev1, {'FILE': 'ok'}) self.assertRevContent(rev3, {'FILE': 'What are you waiting for, christmas?'})
def test_resume_abort(self): c = Connector() (doc, rev1, rev2) = self.createSuspendDoc() with c.resume(doc, rev2) as w: w.writeAll('FILE', 'Hail to the king, baby!') l = c.lookup_doc(doc) self.assertEqual(l.revs(), [rev1]) self.assertEqual(l.preRevs(), [rev2]) w.close() 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 test_update_keep(self): c = Connector() w = self.create("test.format.foo", "test.ignore", [self.store1]) self.assertEqual(w.getType(), "test.format.foo") w.commit() doc = w.getDoc() rev1 = w.getRev() with c.update(doc, rev1, "test.ignore") as w: self.assertEqual(w.getType(), "test.format.foo") w.write('FILE', 'update') w.commit() rev2 = w.getRev() s = c.stat(rev1) self.assertEqual(s.type(), "test.format.foo") s = c.stat(rev2) self.assertEqual(s.type(), "test.format.foo")
def test_good(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', 'update') w.commit() rev = w.getRev() self.assertTrue(c.sync(doc) == rev) l = c.lookup_doc(doc) self.assertEqual(len(l.revs()), 1) self.assertEqual(l.rev(self.store1), rev) self.assertEqual(l.rev(self.store2), rev)
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()))
def test_fork_change(self): c = Connector() w = self.create("test.format.foo", "test.ignore", [self.store1]) self.assertEqual(w.getType(), "test.format.foo") w.commit() doc1 = w.getDoc() rev1 = w.getRev() w = self.fork(rev1, "test.ignore") w.write('FILE', 'update') self.assertEqual(w.getType(), "test.format.foo") w.setType("test.format.bar") self.assertEqual(w.getType(), "test.format.bar") w.commit() doc2 = w.getDoc() rev2 = w.getRev() s = c.stat(rev1) self.assertEqual(s.type(), "test.format.foo") s = c.stat(rev2) self.assertEqual(s.type(), "test.format.bar")