From 1d1fec3ee0328c998989aaa35aabc20e300b7042 Mon Sep 17 00:00:00 2001
From: cipres
Date: Thu, 30 Apr 2020 00:07:20 +0200
Subject: [PATCH] Play nicely with go-ipfs 0.5.0
* deps: use latest py-multicodec
* Embed go-ipfs 0.5.0 and the latest fs-repo-migrations
in the AppImage. Automatic repo migration is on by
default.
* Add galacteek.ipfs.cidhelpers.ipnsKeyCidV1(), which
converts an IPNS key into a CIDv1 with the right multicodec,
that is usable with /ipns/ with go-ipfs 0.5.0
* Make the ipns:// scheme work natively with such CIDs.
All across the browser any IPNS object opened should go
through this scheme (and not dweb:/).
---
AppImage/galacteek-appimage-build | 3 +-
Pipfile | 4 +-
galacteek/application.py | 8 +--
galacteek/core/models/mfs.py | 6 +-
galacteek/core/profile.py | 8 +++
galacteek/core/userdag.py | 14 ++---
galacteek/core/webprofiles.py | 3 -
galacteek/database/models/core.py | 3 +-
galacteek/guientrypoint.py | 1 +
.../hashmarks/default/hashmarks.ipfs.yaml | 4 +-
galacteek/ipfs/cidhelpers.py | 60 +++++++++++++++++--
galacteek/ipfs/distipfsfetch.py | 15 +++--
galacteek/ipfs/ipfsops.py | 10 +++-
galacteek/ui/browser.py | 22 ++++---
galacteek/ui/iprofile.py | 10 ++--
galacteek/ui/peers.py | 2 +-
galacteek/ui/pyramids.py | 19 +++++-
galacteek/ui/resource.py | 2 -
requirements.txt | 4 +-
travis/install.sh | 10 ++--
20 files changed, 150 insertions(+), 58 deletions(-)
diff --git a/AppImage/galacteek-appimage-build b/AppImage/galacteek-appimage-build
index 1a89243f..58de4dc1 100755
--- a/AppImage/galacteek-appimage-build
+++ b/AppImage/galacteek-appimage-build
@@ -89,8 +89,9 @@ cp ../share/icons/galacteek.png $APPDIR/usr/share/icons/hicolor/512x512/apps
find /usr/lib -iname 'libzbar.so*' -exec cp -av {} $APPDIR/usr/lib \;
find /usr/lib -iname 'libjpeg.so*' -exec cp -av {} $APPDIR/usr/lib \;
-# Copy go-ipfs
+# Copy go-ipfs and fs-repo-migrations
cp /tmp/go-ipfs/ipfs $APPDIR/usr/bin
+cp $HOME/bin/fs-repo-migrations $APPDIR/usr/bin
# Remove unnecessary stuff
pushd "$APPDIR"/usr
diff --git a/Pipfile b/Pipfile
index d2d1d6f1..304dc4cd 100644
--- a/Pipfile
+++ b/Pipfile
@@ -10,7 +10,7 @@ jinja2 = ">=2.10.1"
base58 = ">=1.0.2,<2.0"
gitpython = ">=2.1.11"
py-multibase = "==1.0.1"
-py-multicodec = "==0.1.3"
+py-multicodec = "==0.2.1"
py-multihash = ">=0.2.3"
aiofiles = ">=0.4.0"
aiohttp = ">=3.4.4"
@@ -34,7 +34,7 @@ async-timeout = ">=3.0.1"
aiosqlite = ">=0.10.0"
aiodns = ">=2.0.0"
pyld = ">=1.0.5"
-aioipfs = ">=0.4.4"
+aioipfs = ">=0.4.5"
cachetools = ">=3.1.1"
tortoise-orm = "==0.16.5"
pyyaml = ">=5.3.0"
diff --git a/galacteek/application.py b/galacteek/application.py
index 88b15e49..b5e554e4 100644
--- a/galacteek/application.py
+++ b/galacteek/application.py
@@ -59,7 +59,6 @@
from galacteek.core.analyzer import ResourceAnalyzer
from galacteek.core.schemes import SCHEME_MANUAL
-from galacteek.core.schemes import DWebSchemeHandlerNative
from galacteek.core.schemes import DWebSchemeHandlerGateway
from galacteek.core.schemes import EthDNSSchemeHandler
from galacteek.core.schemes import EthDNSProxySchemeHandler
@@ -155,7 +154,7 @@ def ipfsVersion():
async def fetchGoIpfsWrapper(app, timeout=60 * 10):
try:
await asyncio.wait_for(fetchIpfsSoft(
- app, 'go-ipfs', 'ipfs', '0.4.23'), timeout)
+ app, 'go-ipfs', 'ipfs', '0.5.0'), timeout)
except asyncio.TimeoutError:
app.mainWindow.statusMessage(iGoIpfsFetchTimeout())
return None
@@ -787,7 +786,7 @@ async def fetchGoIpfs(self):
ipfsPath = self.which('ipfs')
fsMigratePath = self.which('fs-repo-migrations')
- if fsMigratePath is None and self.cmdArgs.forcegoipfsdl:
+ if fsMigratePath is None or self.cmdArgs.forcegoipfsdl:
await fetchFsMigrateWrapper(self)
if ipfsPath is None or self.cmdArgs.forcegoipfsdl:
@@ -1050,8 +1049,7 @@ def initDapps(self):
self.dappsRegistry = DappsRegistry(self.ethereum, parent=self)
def setupSchemeHandlers(self):
- self.dwebGwSchemeHandler = DWebSchemeHandlerGateway(self)
- self.dwebSchemeHandler = DWebSchemeHandlerNative(self)
+ self.dwebSchemeHandler = DWebSchemeHandlerGateway(self)
self.ensSchemeHandler = EthDNSSchemeHandler(self)
self.ensProxySchemeHandler = EthDNSProxySchemeHandler(self)
self.nativeIpfsSchemeHandler = NativeIPFSSchemeHandler(
diff --git a/galacteek/core/models/mfs.py b/galacteek/core/models/mfs.py
index 3df6c4ad..d356bd4f 100644
--- a/galacteek/core/models/mfs.py
+++ b/galacteek/core/models/mfs.py
@@ -106,8 +106,8 @@ def ipfsPath(self):
return IPFSPath(self.fullPath)
@property
- def dwebUrl(self):
- return QUrl('dweb:{}'.format(self.fullPath))
+ def qIpfsUrl(self):
+ return QUrl(self.ipfsPath.ipfsUrl)
@property
def mimeType(self):
@@ -279,7 +279,7 @@ def mimeData(self, indexes):
nameItem = self.getNameItemFromIdx(idx)
if nameItem:
- mimedata.setUrls([nameItem.dwebUrl])
+ mimedata.setUrls([nameItem.qIpfsUrl])
break
return mimedata
diff --git a/galacteek/core/profile.py b/galacteek/core/profile.py
index e6b8d225..1ba6190a 100644
--- a/galacteek/core/profile.py
+++ b/galacteek/core/profile.py
@@ -155,6 +155,14 @@ async def identityDagGet(self, ipfsop, path, identityUid=None):
path)
)
+ @ipfsOp
+ async def identityGetRaw(self, ipfsop, path, identityUid=None):
+ return await self.cat(os.path.join(
+ 'identities',
+ identityUid if identityUid else self.root['currentIdentityUid'],
+ path)
+ )
+
@ipfsOp
async def getAvatar(self, ipfsop):
return await self.get('avatar')
diff --git a/galacteek/core/userdag.py b/galacteek/core/userdag.py
index 4a03b9dc..4970c889 100644
--- a/galacteek/core/userdag.py
+++ b/galacteek/core/userdag.py
@@ -108,7 +108,7 @@ def ipnsKey(self):
@property
def siteUrl(self):
- return self.sitePath.dwebUrl
+ return self.sitePath.ipfsUrl
@property
def sitePath(self):
@@ -274,7 +274,7 @@ def createFeed(self):
feed.author({
'name': self.profile.userInfo.iphandle
})
- feed.link(href=self.atomFeedPath.dwebUrl, rel='self')
+ feed.link(href=self.atomFeedPath.ipfsUrl, rel='self')
feed.language('en')
return feed
@@ -409,8 +409,8 @@ def feedAddPinRequests(self, requests, feed):
fEntry = feed.add_entry()
fEntry.title('Pin request: {}'.format(req['title']))
- fEntry.id(rpath.dwebUrl)
- fEntry.link(href=rpath.dwebUrl, rel='alternate')
+ fEntry.id(rpath.ipfsUrl)
+ fEntry.link(href=rpath.ipfsUrl, rel='alternate')
fEntry.published(req['date_published'])
fEntry.author({'name': self.profile.userInfo.iphandle})
@@ -421,8 +421,8 @@ def feedAddPosts(self, blogPosts, feed):
fEntry = feed.add_entry()
fEntry.title(post['title'])
- fEntry.id(ppath.dwebUrl)
- fEntry.link(href=ppath.dwebUrl, rel='alternate')
+ fEntry.id(ppath.ipfsUrl)
+ fEntry.link(href=ppath.ipfsUrl, rel='alternate')
fEntry.updated(post['date_modified'])
fEntry.published(post['date_published'])
fEntry.author({'name': self.profile.userInfo.iphandle})
@@ -439,7 +439,7 @@ async def tmplRender(self, tmpl, contained=False, **kw):
profile=self.profile,
dag=self.edag.dagRoot,
siteIpns=self.ipnsKey,
- atomFeedrUrl=self.atomFeedPath.dwebUrl,
+ atomFeedrUrl=self.atomFeedPath.ipfsUrl,
**kw)
async def renderLink(self, tmpl, contained=False, **kw):
diff --git a/galacteek/core/webprofiles.py b/galacteek/core/webprofiles.py
index 059785d7..8e86a4ff 100644
--- a/galacteek/core/webprofiles.py
+++ b/galacteek/core/webprofiles.py
@@ -8,7 +8,6 @@
from galacteek.dweb.webscripts import ethereumClientScripts
from galacteek.core.schemes import SCHEME_DWEB
-from galacteek.core.schemes import SCHEME_DWEBGW
from galacteek.core.schemes import SCHEME_ENS
from galacteek.core.schemes import SCHEME_ENSR
from galacteek.core.schemes import SCHEME_FS
@@ -64,8 +63,6 @@ def installIpfsSchemeHandlers(self):
for scheme in [SCHEME_DWEB, SCHEME_FS]:
self.installHandler(scheme, self.app.dwebSchemeHandler)
- self.installHandler(SCHEME_DWEBGW, self.app.dwebGwSchemeHandler)
-
for scheme in [SCHEME_IPFS, SCHEME_IPNS]:
self.installHandler(scheme, self.app.nativeIpfsSchemeHandler)
diff --git a/galacteek/database/models/core.py b/galacteek/database/models/core.py
index d476b92b..b44b3112 100644
--- a/galacteek/database/models/core.py
+++ b/galacteek/database/models/core.py
@@ -121,7 +121,8 @@ def preferredUrl(self):
iPath = IPFSPath(self.path, autoCidConv=True)
if self.schemepreferred == 'dweb':
return iPath.dwebUrl
- elif not self.schemepreferred or self.schemepreferred == 'ipfs':
+ elif not self.schemepreferred or self.schemepreferred in \
+ ['ipfs', 'ipns']:
return iPath.ipfsUrl
else:
return self.url
diff --git a/galacteek/guientrypoint.py b/galacteek/guientrypoint.py
index 053268b5..b0ccf513 100644
--- a/galacteek/guientrypoint.py
+++ b/galacteek/guientrypoint.py
@@ -131,6 +131,7 @@ def start():
'--migrate',
action='store_true',
dest='migrate',
+ default=True,
help='Activate automatic repository migration')
parser.add_argument(
'--no-release-check',
diff --git a/galacteek/hashmarks/default/hashmarks.ipfs.yaml b/galacteek/hashmarks/default/hashmarks.ipfs.yaml
index a6794e89..da09b438 100644
--- a/galacteek/hashmarks/default/hashmarks.ipfs.yaml
+++ b/galacteek/hashmarks/default/hashmarks.ipfs.yaml
@@ -54,7 +54,7 @@ hashmarks:
description: Hardbin is an encrypted pastebin for IPFS
category: ipfs/apps
icon: /ipfs/QmQZ1PLTZKekXbcLErY2bSnHiqB9vXxkLtPtbqhEPbDHgg
- schemepreferred: dwebgw
+ schemepreferred: dweb
tags:
- '#pastebin'
- '#dapp'
@@ -75,7 +75,7 @@ hashmarks:
date: "2019-07-04T12:00:00-00:00"
category: ipfs/apps
icon: /ipfs/bafybeihbmylhr5aplden7ijet4m6izxn6svq27eykqyiq5tik6mjxsoxjy/mstile-144x144.png
- schemepreferred: dwebgw
+ schemepreferred: dweb
tags:
- '#ipfs'
- '#essays'
diff --git a/galacteek/ipfs/cidhelpers.py b/galacteek/ipfs/cidhelpers.py
index 5e74eeea..b77d0c93 100644
--- a/galacteek/ipfs/cidhelpers.py
+++ b/galacteek/ipfs/cidhelpers.py
@@ -6,6 +6,7 @@
from PyQt5.QtCore import QUrl
from galacteek import log
+from galacteek.ipfs.cid import CIDv1
from galacteek.ipfs.cid import make_cid
from galacteek.ipfs.cid import BaseCID
from galacteek.ipfs.stat import StatInfo
@@ -167,6 +168,21 @@ def cidConvertBase32(cid):
return cid.encode('base32').decode()
+def ipnsKeyCidV1(ipnsKey):
+ """
+ Converts a base58 IPNS key to a CIDv1 with the
+ 'libp2p-key' multicodec.
+ """
+
+ cid = getCID(ipnsKey)
+ if not cid:
+ return None
+
+ # Need to use the libp2p-key multicodec
+ cidV1 = CIDv1('libp2p-key', cid.multihash)
+ return cidV1.encode('base32').decode()
+
+
def cidValid(cid):
"""
Check if the passed argument is a valid IPFS CID
@@ -209,6 +225,10 @@ def domainValid(domain):
r'^(\s*)?(?:fs:|dweb:|dwebgw:|https?://[\w:.-]+)?(?P(/ipfs/)?(?P[a-zA-Z0-9]{46,113})/?(?P[\w<>":;,?!\*%&=@\$~/\s\.\-_\\\'()\+]{1,1024})?)#?(?P[\w_\.\-\+,=/]{1,256})?$', # noqa
flags=re.UNICODE)
+ipfsDomainPathRe = re.compile(
+ r'^(\s*)?(?:http)://(?P[a-z2-7]{59,113})\.ipfs\.(?:[\w]+):(?:[\d]+)/(?P[\w<>"\/:;,?!\*%&=@\$~/\s\.\-_\\\'()\+]{0,1024})#?(?P[\w_\.\-\+,=/]{1,256})?$', # noqa
+ flags=re.UNICODE)
+
# For ipfs://
ipfsPathDedRe = re.compile(
r'^(\s*)?(?:ipfs://)(?P(?P[a-z2-7]{59,113})/?(?P[\w<>"*:;,?!%&=@\$~/\s\.\-_\\\'\+()]{1,1024})?)#?(?P[\w_\+\.\-,=/]{1,256})?$', # noqa
@@ -393,7 +413,10 @@ def ipfsUrl(self):
path=stripIpns(self.fullPath)
)
else:
- return self.dwebUrl
+ return '{scheme}://{path}'.format(
+ scheme=self.scheme,
+ path=stripIpns(self.fullPath)
+ )
else:
return self.dwebUrl
@@ -416,6 +439,28 @@ def __analyze(self):
if len(self.input) > self.maxLength:
return False
+ ma = ipfsRegSearchDomainPath(self.input)
+ if ma:
+ gdict = ma.groupdict()
+ cidStr = gdict.get('rootcid')
+ subpath = gdict.get('subpath')
+
+ if not self.parseCid(cidStr):
+ return False
+
+ if subpath:
+ self._rscPath = os.path.join(
+ joinIpfs(cidStr),
+ subpath
+ )
+ else:
+ self._rscPath = joinIpfs(self.rootCidRepr) + '/'
+
+ self._subPath = subpath
+ self._scheme = 'ipfs'
+ self._fragment = gdict.get('fragment')
+ return True
+
ma = ipfsDedSearchPath(self.input)
if ma:
gdict = ma.groupdict()
@@ -472,15 +517,18 @@ def __analyze(self):
gdict = ma.groupdict()
subpath = gdict.get('subpath')
+ ipnsId32 = ipnsKeyCidV1(gdict.get('fqdn'))
+ _id = ipnsId32 if ipnsId32 else gdict.get('fqdn')
+
if subpath:
self._rscPath = os.path.join(
- joinIpns(gdict.get('fqdn')),
+ joinIpns(_id),
subpath
)
else:
- self._rscPath = joinIpns(gdict.get('fqdn'))
+ self._rscPath = joinIpns(_id)
- self._ipnsId = gdict.get('fqdn')
+ self._ipnsId = _id
self._fragment = gdict.get('fragment')
self._subPath = gdict.get('subpath')
self._scheme = 'ipns'
@@ -624,6 +672,10 @@ def ipfsDedSearchPath(text):
return ipfsPathDedRe.match(text)
+def ipfsRegSearchDomainPath(text):
+ return ipfsDomainPathRe.match(text)
+
+
def ipfsDedSearchPath58(text):
# Like ipfsDedSearchPath() but allows any type of CID (including
# CIDv0) as root CID. Only used to be able to extract the root CID
diff --git a/galacteek/ipfs/distipfsfetch.py b/galacteek/ipfs/distipfsfetch.py
index e31c0298..86231241 100644
--- a/galacteek/ipfs/distipfsfetch.py
+++ b/galacteek/ipfs/distipfsfetch.py
@@ -15,7 +15,7 @@
@async_generator
async def distIpfsExtract(dstdir='.', software='go-ipfs', executable='ipfs',
- site='dist.ipfs.io', version='0.4.23', loop=None,
+ site='dist.ipfs.io', version='0.5.0', loop=None,
sslverify=True):
""" Fetch a distribution archive from dist.ipfs.io and extracts the
@@ -79,14 +79,21 @@ def statusMessage(code, msg):
return False
else:
await yield_(statusMessage(0, 'File found!'))
+
+ csize = 524288
+ ccount = 0
while True:
- data = await resp.content.read(262144)
+ data = await resp.content.read(csize)
if not data:
break
+
+ ccount += 1
await fd.write(data)
bytesRead += len(data)
- await yield_(statusMessage(
- 0, 'received {} bytes'.format(bytesRead)))
+
+ if divmod(ccount, 32)[1] == 0:
+ await yield_(statusMessage(
+ 0, 'received {} bytes'.format(bytesRead)))
await asyncio.sleep(0)
def extract(path, dest):
diff --git a/galacteek/ipfs/ipfsops.py b/galacteek/ipfs/ipfsops.py
index 8645a16b..ff9a76d9 100644
--- a/galacteek/ipfs/ipfsops.py
+++ b/galacteek/ipfs/ipfsops.py
@@ -188,11 +188,13 @@ class IPFSOperator(object):
"""
def __init__(self, client, ctx=None, rsaAgent=None, debug=False,
- offline=False, nsCachePath=None):
+ offline=False, nsCachePath=None,
+ objectMapping=False):
self._lock = asyncio.Lock()
self._id = uuid.uuid1()
self._cache = {}
self._offline = offline
+ self._objectMapping = objectMapping
self._rsaAgent = rsaAgent
self._nsCache = {}
self._nsCachePath = nsCachePath
@@ -529,7 +531,7 @@ async def keysRemove(self, name):
return False
return True
- async def publish(self, path, key='self', timeout=60 * 4,
+ async def publish(self, path, key='self', timeout=60 * 6,
allow_offline=None, lifetime='24h',
resolve=True,
ttl=None, cache=None, cacheOrigin='unknown'):
@@ -1067,6 +1069,10 @@ def ipld(self, cid):
return {"/": cid['Hash']}
def objectPathMap(self, path):
+ if self._objectMapping is False and 0:
+ # No object mapping (don't use any cache)
+ return path
+
ipfsPath = path if isinstance(path, IPFSPath) else \
IPFSPath(path, autoCidConv=True)
diff --git a/galacteek/ui/browser.py b/galacteek/ui/browser.py
index cf5830d5..3c1acf22 100644
--- a/galacteek/ui/browser.py
+++ b/galacteek/ui/browser.py
@@ -1342,6 +1342,10 @@ def pinAll(self):
def currentIpfsObject(self):
return self._currentIpfsObject
+ def fromGateway(self, authority):
+ return authority.endswith(self.gatewayAuthority) or \
+ authority.endswith('ipfs.' + self.gatewayAuthority)
+
def createPageOpsButton(self):
icon = getMimeIcon('text/html')
iconPrinter = getIcon('printer.png')
@@ -1383,7 +1387,7 @@ def onMoveToMfsMenuTriggered(self, action):
cTitle = self.currentPageTitle if self.currentPageTitle else ''
- ensure(runDialogASync(
+ ensure(runDialogAsync(
TitleInputDialog, cTitle,
accepted=functools.partial(
self.onMoveToMfsWithTitle,
@@ -1866,6 +1870,8 @@ async def onUrlChanged(self, url):
sHandler = self.webEngineView.webProfile.urlSchemeHandler(
url.scheme().encode())
+ urlAuthority = url.authority()
+
if url.scheme() in [SCHEME_IPFS, SCHEME_IPNS, SCHEME_DWEB]:
self.urlZone.setStyleSheet('''
QLineEdit {
@@ -1883,20 +1889,22 @@ async def onUrlChanged(self, url):
self.followIpnsAction.setEnabled(
self.currentIpfsObject.isIpns)
self.curObjectCtrl.show()
- elif url.authority() == self.gatewayAuthority:
+ elif self.fromGateway(urlAuthority):
# dweb:/ with IPFS gateway's authority
# Content loaded from IPFS gateway, this is IPFS content
- urlString = url.toDisplayString(
- QUrl.RemoveAuthority | QUrl.RemoveScheme)
+ if 0:
+ urlString = url.toDisplayString(
+ QUrl.RemoveAuthority | QUrl.RemoveScheme)
- self._currentIpfsObject = IPFSPath(urlString)
+ self._currentIpfsObject = IPFSPath(
+ url.toString(), autoCidConv=True)
if self.currentIpfsObject.valid:
log.debug('Current IPFS object: {0}'.format(
repr(self.currentIpfsObject)))
- url = QUrl(self.currentIpfsObject.dwebGwUrl)
+ url = QUrl(self.currentIpfsObject.dwebUrl)
self.urlZone.clear()
self.urlZone.insert(url.toString())
@@ -1996,7 +2004,7 @@ def onLoadProgress(self, progress):
def browseFsPath(self, path, schemePreferred='ipfs'):
def _handle(iPath):
if iPath.valid and not schemePreferred or \
- schemePreferred == 'ipfs':
+ schemePreferred in [SCHEME_IPFS, SCHEME_IPNS]:
self.enterUrl(QUrl(iPath.ipfsUrl))
elif iPath.valid and schemePreferred == 'dweb':
self.enterUrl(QUrl(iPath.dwebUrl))
diff --git a/galacteek/ui/iprofile.py b/galacteek/ui/iprofile.py
index e70c2b36..309eb25f 100644
--- a/galacteek/ui/iprofile.py
+++ b/galacteek/ui/iprofile.py
@@ -16,7 +16,6 @@
from PyQt5.QtGui import QPixmap
from PyQt5.QtGui import QImage
-from galacteek import asyncify
from galacteek import ensure
from galacteek import log
from galacteek.ipfs.wrappers import ipfsOp
@@ -252,18 +251,17 @@ def loadPlanets(self, planetsList=None):
self.ui.vPlanet.setEnabled(False)
- @asyncify
async def loadIcon(self):
- avatar = await self.profile.userInfo.identityDagGet('avatar')
+ avatar = await self.profile.userInfo.identityGetRaw('avatar')
if isinstance(avatar, bytes):
try:
img1 = QImage()
img1.loadFromData(avatar)
- img = img1.scaledToWidth(256)
+ img = img1.scaledToWidth(128)
self.ui.iconPixmap.setPixmap(QPixmap.fromImage(img))
- except Exception:
- pass
+ except Exception as err:
+ log.debug(str(err))
def changeIcon(self):
fps = filesSelectImages()
diff --git a/galacteek/ui/peers.py b/galacteek/ui/peers.py
index 68a40c73..080175b7 100644
--- a/galacteek/ui/peers.py
+++ b/galacteek/ui/peers.py
@@ -658,7 +658,7 @@ async def followPeerFeed(self, op, peerCtx):
ipfsPath = IPFSPath(path)
try:
- await self.app.sqliteDb.feeds.follow(ipfsPath.dwebUrl)
+ await self.app.sqliteDb.feeds.follow(ipfsPath.ipfsUrl)
except Exception:
# TODO
pass
diff --git a/galacteek/ui/pyramids.py b/galacteek/ui/pyramids.py
index ffbf4c1b..3442b746 100644
--- a/galacteek/ui/pyramids.py
+++ b/galacteek/ui/pyramids.py
@@ -26,6 +26,7 @@
from galacteek.ipfs.cidhelpers import IPFSPath
from galacteek.ipfs.cidhelpers import joinIpns
+from galacteek.ipfs.cidhelpers import ipnsKeyCidV1
from galacteek.ipfs import ipfsOp
from galacteek.ipfs.stat import StatInfo
from galacteek.ipfs.dag import EvolvingDAG
@@ -55,6 +56,7 @@
from .i18n import iRemove
from .i18n import iHelp
from .i18n import iHashmark
+from .i18n import iOpen
def iCreateRawPyramid():
@@ -368,6 +370,10 @@ def __init__(self, pyramid, icon=None, parent=None):
self,
triggered=self.onOpenLatest)
self.openLatestAction.setEnabled(False)
+ self.openAction = QAction(getIcon('pyramid-aqua.png'),
+ iOpen(),
+ self,
+ triggered=self.onOpen)
self.publishCurrentClipAction = QAction(
getIcon('clipboard.png'),
@@ -496,6 +502,8 @@ def createExtraActions(self):
pass
def buildMenu(self):
+ self.menu.addAction(self.openAction)
+ self.menu.addSeparator()
self.menu.addAction(self.openLatestAction)
self.menu.addSeparator()
self.menu.addAction(self.publishCurrentClipAction)
@@ -557,6 +565,7 @@ def updateToolTip(self):
Description: {descr}
IPNS key: {ipns}
+ IPNS key (CIDv1): {ipnsv1}
Description: {descr}
IPNS key: {ipns}
+ IPNS key (CIDv1): {ipnsv1}
=2.0.0
aiofiles>=0.4.0
aiohttp>=3.4.4
-aioipfs>=0.4.4
+aioipfs>=0.4.5
aiojobs>=0.2.2
aiosqlite>=0.10.0
async-generator>=1.10
@@ -20,7 +20,7 @@ multiaddr>=0.0.8
pillow>=6.0.0
protobuf>=3.6.1
py-multibase==1.0.1
-py-multicodec==0.1.3
+py-multicodec==0.2.1
py-multihash>=0.2.3
pycryptodomex>=3.6.6
pygments>=2.3.1
diff --git a/travis/install.sh b/travis/install.sh
index 532b7cb4..e40c7804 100644
--- a/travis/install.sh
+++ b/travis/install.sh
@@ -17,8 +17,8 @@ if [ "$TRAVIS_OS_NAME" = "linux" ]; then
wget https://dist.ipfs.io/go-ipfs/v${GO_IPFS_VERSION}/go-ipfs_v${GO_IPFS_VERSION}_linux-amd64.tar.gz
tar -C $HOME -xzvf go-ipfs_v${GO_IPFS_VERSION}_linux-amd64.tar.gz
- #wget https://dist.ipfs.io/fs-repo-migrations/v${FS_MIGRATE_VERSION}/fs-repo-migrations_v${FS_MIGRATE_VERSION}_linux-amd64.tar.gz
- #tar -C $HOME -xzvf fs-repo-migrations_v${FS_MIGRATE_VERSION}_linux-amd64.tar.gz
+ wget https://dist.ipfs.io/fs-repo-migrations/v${FS_MIGRATE_VERSION}/fs-repo-migrations_v${FS_MIGRATE_VERSION}_linux-amd64.tar.gz
+ tar -C $HOME -xzvf fs-repo-migrations_v${FS_MIGRATE_VERSION}_linux-amd64.tar.gz
wget https://github.com/wasmerio/wasmer/releases/download/0.12.0/wasmer-linux-amd64.tar.gz
tar -C $HOME -xzvf wasmer-linux-amd64.tar.gz
@@ -34,11 +34,13 @@ if [ "$TRAVIS_OS_NAME" = "osx" ]; then
wget https://dist.ipfs.io/go-ipfs/v${GO_IPFS_VERSION}/go-ipfs_v${GO_IPFS_VERSION}_darwin-amd64.tar.gz
tar -C $HOME -xzvf go-ipfs_v${GO_IPFS_VERSION}_darwin-amd64.tar.gz
- #wget https://dist.ipfs.io/fs-repo-migrations/v${FS_MIGRATE_VERSION}/fs-repo-migrations_v${FS_MIGRATE_VERSION}_darwin-amd64.tar.gz
- #tar -C $HOME -xzvf fs-repo-migrations_v${FS_MIGRATE_VERSION}_darwin-amd64.tar.gz
+ wget https://dist.ipfs.io/fs-repo-migrations/v${FS_MIGRATE_VERSION}/fs-repo-migrations_v${FS_MIGRATE_VERSION}_darwin-amd64.tar.gz
+ tar -C $HOME -xzvf fs-repo-migrations_v${FS_MIGRATE_VERSION}_darwin-amd64.tar.gz
fi
mv $HOME/go-ipfs/ipfs $HOME/bin
+mv $HOME/fs-repo-migrations/fs-repo-migrations $HOME/bin
+
$HOME/bin/ipfs init
export PYTHONPATH=$PYTHONPATH:/usr/local/lib/python3.7/dist-packages