+
+
+For translators
+^^^^^^^^^^^^^^^
+
+We are using `transifex `_ to coordinate translation efforts. If you want to contribute, just sign up there and send us your translations.
+
+
+Translating help documents
+--------------------------
+
+There are two sets of online documents that need translation. One is
+https://leap.se/docs, and the other is https://bitmask.net/help. Both are
+maintained in git repos (`leap.se `_ and `bitmask.net `_).
+
+In the repo for bitmask.net there are some explanations about how to contribute
+to those repos (using the online github editor, or using git directly).
+
+
+Human interaction
+-----------------
+We're hanging out in the #leap channel on the freenode network. There's also a
+spanish channel at #bitmask-es.
--
cgit v1.2.3
From b370dfa37265ec7df99c8a85f2b7b7866a9a6b74 Mon Sep 17 00:00:00 2001
From: kwadronaut
Date: Sat, 7 Nov 2015 15:01:11 +0100
Subject: Debian capitalization
Solves https://www.transifex.com/otf/bitmask/translate/#es/$/31977728
---
data/ts/en_US.ts | 2 +-
docker/README.rst | 6 +++---
docs/dev/environment.rst | 4 ++--
docs/dev/tests.rst | 2 +-
docs/pkg/debian.rst | 2 +-
src/leap/bitmask/platform_init/initializers.py | 2 +-
6 files changed, 9 insertions(+), 9 deletions(-)
diff --git a/data/ts/en_US.ts b/data/ts/en_US.ts
index b6fcc5da..b7cd6d26 100644
--- a/data/ts/en_US.ts
+++ b/data/ts/en_US.ts
@@ -1622,7 +1622,7 @@ Export canceled.
-
+
diff --git a/docker/README.rst b/docker/README.rst
index dcad0ac6..70d44809 100644
--- a/docker/README.rst
+++ b/docker/README.rst
@@ -21,10 +21,10 @@ will be used to run bitmask.
python dependencies, running bitmask, etc.
-debian/
+Debian/
-------
-``apt-bitmask.sh`` script that installs bitmask from the debian packages.
+``apt-bitmask.sh`` script that installs bitmask from the Debian packages.
``bitmask-on-docker.sh`` installs bitmask and runs it in a dummy X server,
waits a little and takes a screenshot.
@@ -32,7 +32,7 @@ waits a little and takes a screenshot.
``leap-experimental.key`` is needed by ``apt-bitmask.sh`` to ``apt-key add``
and verify apt sources.
-``run-docker-for-bitmask.sh`` is a helper script that runs an ubuntu/debian
+``run-docker-for-bitmask.sh`` is a helper script that runs an Ubuntu/Debian
container ready to run the ``apt-bitmask.sh`` command, it does (among other
stuff) X11 forwarding to display Bitmask UI on the host linux.
diff --git a/docs/dev/environment.rst b/docs/dev/environment.rst
index a3184b01..99600ec8 100644
--- a/docs/dev/environment.rst
+++ b/docs/dev/environment.rst
@@ -34,7 +34,7 @@ Bitmask depends on these base libraries:
Debian
^^^^^^
-In debian-based systems, you can get everything you need:
+In Debian-based systems, you can get everything you need:
.. include:: quickstart.rst
:start-after: begin-debian-deps
@@ -82,7 +82,7 @@ Avoid compiling PySide inside a virtualenv
If you attempt to install PySide inside a virtualenv as part of the rest of the dependencies using pip, basically it will take ages to compile.
-As a workaround, you can run the following script after creating your virtualenv. It will symlink to your global PySide installation (*this is the recommended way if you are running a debian-based system*)::
+As a workaround, you can run the following script after creating your virtualenv. It will symlink to your global PySide installation (*this is the recommended way if you are running a Debian-based system*)::
(bitmask)$ pkg/postmkvenv.sh
diff --git a/docs/dev/tests.rst b/docs/dev/tests.rst
index d55c206a..bdefcfdc 100644
--- a/docs/dev/tests.rst
+++ b/docs/dev/tests.rst
@@ -16,7 +16,7 @@ Testing dependencies
have a look at ``pkg/test-requirements.pip``
The ``./run_tests.sh`` command should install all of them in your virtualenv for you.
-If you prefer to install them system wide, this should do in a debian system::
+If you prefer to install them system wide, this should do in a Debian system::
$ apt-get install python-nose python-mock python-coverage
diff --git a/docs/pkg/debian.rst b/docs/pkg/debian.rst
index 204d4073..13976e2b 100644
--- a/docs/pkg/debian.rst
+++ b/docs/pkg/debian.rst
@@ -3,7 +3,7 @@
Debian
======
-This section documents all related to the debian package.
+This section documents all related to the Debian package.
Dependencies
diff --git a/src/leap/bitmask/platform_init/initializers.py b/src/leap/bitmask/platform_init/initializers.py
index eb892cce..82a229ae 100644
--- a/src/leap/bitmask/platform_init/initializers.py
+++ b/src/leap/bitmask/platform_init/initializers.py
@@ -126,7 +126,7 @@ def check_missing():
if alert_missing and not flags.STANDALONE:
# We refuse to install missing stuff if not running with standalone
# flag. Right now we rely on the flag alone, but we can disable this
- # by overwriting some constant from within the debian package.
+ # by overwriting some constant from within the Debian package.
alert_missing = False
complain_missing = True
--
cgit v1.2.3
From 93d9469194ca567d14660572c65996b6330088b2 Mon Sep 17 00:00:00 2001
From: kwadronaut
Date: Sat, 7 Nov 2015 17:08:45 +0100
Subject: Change title 'Missing Bitmask helpers'
solves https://www.transifex.com/otf/bitmask/translate/#ar/$/31977726
---
src/leap/bitmask/platform_init/initializers.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/leap/bitmask/platform_init/initializers.py b/src/leap/bitmask/platform_init/initializers.py
index 82a229ae..4e8bbdbb 100644
--- a/src/leap/bitmask/platform_init/initializers.py
+++ b/src/leap/bitmask/platform_init/initializers.py
@@ -465,7 +465,7 @@ def _get_missing_complain_dialog(stuff):
self.setLayout(mainLayout)
msg = ComplainDialog()
- msg.setWindowTitle(msg.tr("Missing Bitmask helpers"))
+ msg.setWindowTitle(msg.tr("Missing Bitmask helper files"))
return msg
--
cgit v1.2.3
From 077a36d20f697865cb334dd809ad9bd201adcb10 Mon Sep 17 00:00:00 2001
From: kwadronaut
Date: Sat, 7 Nov 2015 17:47:27 +0100
Subject: solved transifex issues, language
https://www.transifex.com/otf/bitmask/translate/#ar/$/31977726
https://www.transifex.com/otf/bitmask/translate/#nl/$/32117870
https://www.transifex.com/otf/bitmask/translate/#ar/$/22113277
https://www.transifex.com/otf/bitmask/translate/#nl/$/22113279
---
src/leap/bitmask/gui/eip_status.py | 2 +-
src/leap/bitmask/gui/logwindow.py | 4 ++--
2 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/src/leap/bitmask/gui/eip_status.py b/src/leap/bitmask/gui/eip_status.py
index 64a408c4..470ef88a 100644
--- a/src/leap/bitmask/gui/eip_status.py
+++ b/src/leap/bitmask/gui/eip_status.py
@@ -733,7 +733,7 @@ class EIPStatusWidget(QtGui.QWidget):
self.set_eip_status(
# XXX this should change to polkit-kde where
# applicable.
- self.tr("We could not find any authentication agent in your "
+ self.tr("We could not find any authentication agent on your "
"system. Make sure you have "
"polkit-gnome-authentication-agent-1 running and "
"try again."),
diff --git a/src/leap/bitmask/gui/logwindow.py b/src/leap/bitmask/gui/logwindow.py
index 718269c9..5d8c99fc 100644
--- a/src/leap/bitmask/gui/logwindow.py
+++ b/src/leap/bitmask/gui/logwindow.py
@@ -173,7 +173,7 @@ class LoggerWindow(QtGui.QDialog):
:type sending: bool
"""
if sending:
- self.ui.btnPastebin.setText(self.tr("Sending to pastebin..."))
+ self.ui.btnPastebin.setText(self.tr("Sending to Pastebin.com…"))
self.ui.btnPastebin.setEnabled(False)
else:
self.ui.btnPastebin.setText(self.tr("Send to Pastebin.com"))
@@ -193,7 +193,7 @@ class LoggerWindow(QtGui.QDialog):
# We save the dialog in an instance member to avoid dialog being
# deleted right after we exit this method
self._msgBox = msgBox = QtGui.QMessageBox(
- QtGui.QMessageBox.Information, self.tr("Pastebin OK"), msg)
+ QtGui.QMessageBox.Information, self.tr("Pastebin is OK"), msg)
msgBox.setWindowModality(QtCore.Qt.NonModal)
msgBox.show()
--
cgit v1.2.3
From 65f7d1baf31295803f935ac726f4ad95d3c3ca14 Mon Sep 17 00:00:00 2001
From: Ivan Alejandro
Date: Mon, 9 Nov 2015 12:04:54 -0300
Subject: [i18n] update source strings
---
data/ts/en_US.ts | 111 +++++++++++++++++++++++++++++--------------------------
1 file changed, 58 insertions(+), 53 deletions(-)
diff --git a/data/ts/en_US.ts b/data/ts/en_US.ts
index b7cd6d26..dffb64d3 100644
--- a/data/ts/en_US.ts
+++ b/data/ts/en_US.ts
@@ -410,7 +410,7 @@ Export canceled.
-
+
@@ -489,21 +489,11 @@ Export canceled.
-
-
-
-
-
-
-
-
-
-
@@ -519,6 +509,16 @@ Export canceled.
+
+
+
+
+
+
+
+
+
+ LoginWidget
@@ -641,165 +641,170 @@ Export canceled.
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
+
+
+
+
+ MainWindow
@@ -1060,13 +1065,13 @@ Export canceled.
-
-
+
+
-
-
+
+
@@ -1597,11 +1602,6 @@ Export canceled.
-
-
-
-
-
@@ -1612,6 +1612,11 @@ Export canceled.
+
+
+
+
+ msgstr
@@ -1622,7 +1627,7 @@ Export canceled.
-
+
--
cgit v1.2.3
From fca2246011b8c2402977fde93291d46a9a3438fb Mon Sep 17 00:00:00 2001
From: Ivan Alejandro
Date: Mon, 9 Nov 2015 13:02:45 -0300
Subject: [bug] open email help link on browser
- Resolves: #7585
---
changes/next-changelog.rst | 1 +
src/leap/bitmask/gui/ui/mail_status.ui | 3 +++
2 files changed, 4 insertions(+)
diff --git a/changes/next-changelog.rst b/changes/next-changelog.rst
index 54b2b2ed..d1623d6f 100644
--- a/changes/next-changelog.rst
+++ b/changes/next-changelog.rst
@@ -18,6 +18,7 @@ Bugfixes
~~~~~~~~
- `#7568 `_: Fix typo on signal name.
- `#7583 `_: Fix set_soledad_auth_token event callback signature.
+- `#7585 `_: Open email help link on browser.
- `#1235 `_: Description for the fixed stuff corresponding with issue #1235.
- Bugfix without related issue number.
diff --git a/src/leap/bitmask/gui/ui/mail_status.ui b/src/leap/bitmask/gui/ui/mail_status.ui
index 3f103ef6..89e1843f 100644
--- a/src/leap/bitmask/gui/ui/mail_status.ui
+++ b/src/leap/bitmask/gui/ui/mail_status.ui
@@ -110,6 +110,9 @@ margin-top:5px;
-1
+
+ true
+
--
cgit v1.2.3
From f4b0c01b6737e4266f12276e6b2a058bf3c0f743 Mon Sep 17 00:00:00 2001
From: Ruben Pollan
Date: Wed, 11 Nov 2015 19:42:09 +0100
Subject: [but] Fix errback on InvalidAuthToken
- Related: #7583
---
changes/next-changelog.rst | 1 +
src/leap/bitmask/services/soledad/soledadbootstrapper.py | 2 +-
2 files changed, 2 insertions(+), 1 deletion(-)
diff --git a/changes/next-changelog.rst b/changes/next-changelog.rst
index d1623d6f..22af9bd8 100644
--- a/changes/next-changelog.rst
+++ b/changes/next-changelog.rst
@@ -19,6 +19,7 @@ Bugfixes
- `#7568 `_: Fix typo on signal name.
- `#7583 `_: Fix set_soledad_auth_token event callback signature.
- `#7585 `_: Open email help link on browser.
+- `#7598 `_: Fix errback on InvalidAuthToken.
- `#1235 `_: Description for the fixed stuff corresponding with issue #1235.
- Bugfix without related issue number.
diff --git a/src/leap/bitmask/services/soledad/soledadbootstrapper.py b/src/leap/bitmask/services/soledad/soledadbootstrapper.py
index 60a2130b..a10a2731 100644
--- a/src/leap/bitmask/services/soledad/soledadbootstrapper.py
+++ b/src/leap/bitmask/services/soledad/soledadbootstrapper.py
@@ -654,7 +654,7 @@ class Syncer(object):
logger.error('Invalid auth token while trying to sync Soledad')
self._signaler.signal(
self._signaler.soledad_invalid_auth_token)
- self._callback_deferred.fail(failure)
+ self._callback_deferred.errback(failure)
elif failure.check(sqlite_ProgrammingError,
sqlcipher_ProgrammingError):
logger.exception("%r" % (failure.value,))
--
cgit v1.2.3
From b6db2310f7595bdd6b93a2cab5680abbe5ce6599 Mon Sep 17 00:00:00 2001
From: Ivan Alejandro
Date: Tue, 10 Nov 2015 14:18:49 -0300
Subject: [i18n] do not translate https label text
---
changes/next-changelog.rst | 1 +
src/leap/bitmask/gui/ui/wizard.ui | 4 ++--
2 files changed, 3 insertions(+), 2 deletions(-)
diff --git a/changes/next-changelog.rst b/changes/next-changelog.rst
index 22af9bd8..c40257b8 100644
--- a/changes/next-changelog.rst
+++ b/changes/next-changelog.rst
@@ -21,6 +21,7 @@ Bugfixes
- `#7585 `_: Open email help link on browser.
- `#7598 `_: Fix errback on InvalidAuthToken.
- `#1235 `_: Description for the fixed stuff corresponding with issue #1235.
+- Do not translate 'https' text on QLabel.
- Bugfix without related issue number.
Misc
diff --git a/src/leap/bitmask/gui/ui/wizard.ui b/src/leap/bitmask/gui/ui/wizard.ui
index b125577e..37226d13 100644
--- a/src/leap/bitmask/gui/ui/wizard.ui
+++ b/src/leap/bitmask/gui/ui/wizard.ui
@@ -316,7 +316,7 @@
- https://
+ https://Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
@@ -339,7 +339,7 @@
- https://
+ https://Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
--
cgit v1.2.3
From 2a124d7352518cd2a08b01561eb6621b2bd74748 Mon Sep 17 00:00:00 2001
From: Ivan Alejandro
Date: Mon, 16 Nov 2015 14:54:20 -0300
Subject: [feat] use bitmask repo instead of leap.se
Also map 'sana' (codename for kali linux 2.0) to jessie.
---
docker/debian/apt-bitmask.sh | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/docker/debian/apt-bitmask.sh b/docker/debian/apt-bitmask.sh
index 59226be1..99c5f07e 100755
--- a/docker/debian/apt-bitmask.sh
+++ b/docker/debian/apt-bitmask.sh
@@ -20,6 +20,7 @@ distro(){
['qiana']='trusty'
['rebecca']='trusty'
['rafaela']='trusty'
+ ['sana']='jessie'
)
# if name is in the above list -> replace
@@ -116,8 +117,7 @@ else # $REPO == 'experimental'
apt-key add leap-experimental.key
fi
-echo "deb http://deb.leap.se/$REPO $DISTRO main" > /etc/apt/sources.list.d/bitmask.list
-echo "deb-src http://deb.leap.se/$REPO $DISTRO main" >> /etc/apt/sources.list.d/bitmask.list
+echo "deb http://deb.bitmask.net/$REPO $DISTRO main" > /etc/apt/sources.list.d/bitmask.list
apt-get update
apt-get install -y bitmask
--
cgit v1.2.3
From 97de43f5ef1b7fa4735e3371581bfaf4c3919de3 Mon Sep 17 00:00:00 2001
From: Kali Kaneko
Date: Mon, 30 Nov 2015 12:12:57 -0400
Subject: [docs] fix outdated signature description
---
src/leap/bitmask/services/mail/imap.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/leap/bitmask/services/mail/imap.py b/src/leap/bitmask/services/mail/imap.py
index 5934756d..b06c1d4a 100644
--- a/src/leap/bitmask/services/mail/imap.py
+++ b/src/leap/bitmask/services/mail/imap.py
@@ -61,7 +61,7 @@ def start_imap_service(*args, **kwargs):
"""
Initializes and run imap service.
- :returns: twisted.internet.task.LoopingCall instance
+ :returns: LeapIMAPFactory instance
"""
from leap.bitmask.config import flags
logger.debug('Launching imap service')
--
cgit v1.2.3
From 8d3309701af51df3046aa0df10545dfa35a64ef7 Mon Sep 17 00:00:00 2001
From: Kali Kaneko
Date: Mon, 30 Nov 2015 12:15:09 -0400
Subject: [feat] multi-user events.
Adapt to users emitting the userid/uuid too.
- Resolves: #7656
- Releases: 0.10.0
---
changes/next-changelog.rst | 3 ++-
src/leap/bitmask/gui/mail_status.py | 11 ++++++++---
src/leap/bitmask/services/mail/conductor.py | 3 ++-
3 files changed, 12 insertions(+), 5 deletions(-)
diff --git a/changes/next-changelog.rst b/changes/next-changelog.rst
index c40257b8..77094e78 100644
--- a/changes/next-changelog.rst
+++ b/changes/next-changelog.rst
@@ -11,7 +11,8 @@ I've added a new category `Misc` so we can track doc/style/packaging stuff.
Features
~~~~~~~~
- `#7552 `_: Improve UI message and add some margin above the msg box.
-- `#1234 `_: Description of the new feature corresponding with issue #1234.
+- `#7552 `_: Improve UI message and add some margin above the msg box.
+- `#7656 `_: Adapt to multi-user aware events.
- New feature without related issue number.
Bugfixes
diff --git a/src/leap/bitmask/gui/mail_status.py b/src/leap/bitmask/gui/mail_status.py
index f7957c95..419a85c0 100644
--- a/src/leap/bitmask/gui/mail_status.py
+++ b/src/leap/bitmask/gui/mail_status.py
@@ -233,12 +233,15 @@ class MailStatusWidget(QtGui.QWidget):
self._action_mail_status.setText(tray_status)
self._update_systray_tooltip()
- def _mail_handle_soledad_events(self, event, content):
+ def _mail_handle_soledad_events(self, event, user_data, content=""):
"""
Callback for handling events that are emitted from Soledad
:param event: The event that triggered the callback.
:type event: str
+ :param user_id: The user_data of the soledad user. Ignored right now,
+ since we're only contemplating single-user in soledad.
+ :type user_id: dict
:param content: The content of the event.
:type content: dict
"""
@@ -346,7 +349,7 @@ class MailStatusWidget(QtGui.QWidget):
logger.warning("don't know to to handle %s" % (event,))
self._set_mail_status(ext_status, ready=1)
- def _mail_handle_smtp_events(self, event):
+ def _mail_handle_smtp_events(self, event, content=""):
"""
Callback for the SMTP events
@@ -380,12 +383,14 @@ class MailStatusWidget(QtGui.QWidget):
# ----- XXX deprecate (move to mail conductor)
- def _mail_handle_imap_events(self, event, content):
+ def _mail_handle_imap_events(self, event, uuid, content=""):
"""
Callback for the IMAP events
:param event: The event that triggered the callback.
:type event: str
+ :param uuid: The UUID for the user. Ignored right now.
+ :type uuid: str
:param content: The content of the event.
:type content: list
"""
diff --git a/src/leap/bitmask/services/mail/conductor.py b/src/leap/bitmask/services/mail/conductor.py
index b79ea9c7..738531e6 100644
--- a/src/leap/bitmask/services/mail/conductor.py
+++ b/src/leap/bitmask/services/mail/conductor.py
@@ -73,12 +73,13 @@ class IMAPControl(object):
self._backend.imap_stop_service()
- def _handle_imap_events(self, event, content):
+ def _handle_imap_events(self, event, userid=None, content=None):
"""
Callback handler for the IMAP events
:param event: The event that triggered the callback.
:type event: str
+ :param userid: The user id of the logged in user. Ignored.
:param content: The content of the event.
:type content: list
"""
--
cgit v1.2.3
From 6c0299e7e2df65651ff8738fa18acbc08af18c32 Mon Sep 17 00:00:00 2001
From: Kali Kaneko
Date: Mon, 30 Nov 2015 16:31:10 -0400
Subject: [style] autopep8
---
src/leap/bitmask/services/mail/conductor.py | 2 ++
1 file changed, 2 insertions(+)
diff --git a/src/leap/bitmask/services/mail/conductor.py b/src/leap/bitmask/services/mail/conductor.py
index 738531e6..b94b3cc8 100644
--- a/src/leap/bitmask/services/mail/conductor.py
+++ b/src/leap/bitmask/services/mail/conductor.py
@@ -34,6 +34,7 @@ class IMAPControl(object):
"""
Methods related to IMAP control.
"""
+
def __init__(self):
"""
Initializes smtp variables.
@@ -118,6 +119,7 @@ class IMAPControl(object):
class SMTPControl(object):
+
def __init__(self):
"""
Initializes smtp variables.
--
cgit v1.2.3
From 98384361a7c49ad4e0ff0127fd923a8b72cc910a Mon Sep 17 00:00:00 2001
From: Kali Kaneko
Date: Tue, 8 Dec 2015 21:04:11 -0400
Subject: [feat] adapt to use cred-based authentication for imap
This includes getting the token for the imap authentication, and
displaying it on the help window.
- Resolves: #4469
- Releases: 0.10.0
---
changes/next-changelog.rst | 5 ++--
src/leap/bitmask/backend/api.py | 2 ++
src/leap/bitmask/backend/components.py | 23 ++++++++++++++++++
src/leap/bitmask/backend/leapbackend.py | 7 ++++++
src/leap/bitmask/backend/leapsignaler.py | 1 +
src/leap/bitmask/gui/mainwindow.py | 18 +++++++++++++-
src/leap/bitmask/services/mail/imap.py | 31 ++++++++++++------------
src/leap/bitmask/services/mail/imapcontroller.py | 8 +++---
8 files changed, 71 insertions(+), 24 deletions(-)
diff --git a/changes/next-changelog.rst b/changes/next-changelog.rst
index 77094e78..c359b4e2 100644
--- a/changes/next-changelog.rst
+++ b/changes/next-changelog.rst
@@ -1,4 +1,4 @@
-0.9.2 - xxx
+0.10.0 - xxx
+++++++++++++++++++++++++++++++
Please add lines to this file, they will be moved to the CHANGELOG.rst during
@@ -11,8 +11,9 @@ I've added a new category `Misc` so we can track doc/style/packaging stuff.
Features
~~~~~~~~
- `#7552 `_: Improve UI message and add some margin above the msg box.
-- `#7552 `_: Improve UI message and add some margin above the msg box.
- `#7656 `_: Adapt to multi-user aware events.
+- `#4469 `_: Display randomly generated service token on the Help Window.
+- `#1234 `_: Description of the new feature corresponding with issue #1234.
- New feature without related issue number.
Bugfixes
diff --git a/src/leap/bitmask/backend/api.py b/src/leap/bitmask/backend/api.py
index 48aa2090..134a2d56 100644
--- a/src/leap/bitmask/backend/api.py
+++ b/src/leap/bitmask/backend/api.py
@@ -57,6 +57,7 @@ API = (
"soledad_change_password",
"soledad_close",
"soledad_load_offline",
+ "soledad_get_service_token",
"tear_fw_down",
"bitmask_root_vpn_down",
"user_cancel_login",
@@ -135,6 +136,7 @@ SIGNALS = (
"soledad_offline_finished",
"soledad_password_change_error",
"soledad_password_change_ok",
+ "soledad_got_service_token",
"srp_auth_bad_user_or_password",
"srp_auth_connection_error",
"srp_auth_error",
diff --git a/src/leap/bitmask/backend/components.py b/src/leap/bitmask/backend/components.py
index 5f34d290..a07d3bad 100644
--- a/src/leap/bitmask/backend/components.py
+++ b/src/leap/bitmask/backend/components.py
@@ -763,6 +763,7 @@ class Soledad(object):
self._signaler = signaler
self._soledad_bootstrapper = SoledadBootstrapper(signaler)
self._soledad_defer = None
+ self._service_tokens = {}
def bootstrap(self, username, domain, password):
"""
@@ -786,6 +787,7 @@ class Soledad(object):
provider_config, username, password,
download_if_needed=True)
self._soledad_defer.addCallback(self._set_proxies_cb)
+ self._soledad_defer.addCallback(self._set_service_tokens_cb)
else:
if self._signaler is not None:
self._signaler.signal(self._signaler.soledad_bootstrap_failed)
@@ -793,6 +795,21 @@ class Soledad(object):
return self._soledad_defer
+ def _set_service_tokens_cb(self, result):
+
+ def register_imap_token(imap_token):
+ self._service_tokens['imap'] = imap_token
+ if self._signaler is not None:
+ self._signaler.signal(
+ self._signaler.soledad_got_service_token,
+ ('imap', imap_token))
+
+ sol = self._soledad_bootstrapper.soledad
+ d = sol.get_or_create_service_token('imap')
+ d.addCallback(register_imap_token)
+ d.addCallback(lambda _: result)
+ return d
+
def _set_proxies_cb(self, _):
"""
Update the soledad and keymanager proxies to reference the ones created
@@ -803,6 +820,12 @@ class Soledad(object):
zope.proxy.setProxiedObject(self._keymanager_proxy,
self._soledad_bootstrapper.keymanager)
+ def get_service_token(self, service):
+ """
+ Get an authentication token for a given service.
+ """
+ return self._service_tokens.get(service, '')
+
def load_offline(self, username, password, uuid):
"""
Load the soledad database in offline mode.
diff --git a/src/leap/bitmask/backend/leapbackend.py b/src/leap/bitmask/backend/leapbackend.py
index cf45c4f8..d0668a1c 100644
--- a/src/leap/bitmask/backend/leapbackend.py
+++ b/src/leap/bitmask/backend/leapbackend.py
@@ -35,6 +35,7 @@ class LeapBackend(Backend):
"""
Backend server subclass, used to implement the API methods.
"""
+
def __init__(self, bypass_checks=False, frontend_pid=None):
"""
Constructor for the backend.
@@ -438,6 +439,12 @@ class LeapBackend(Backend):
"""
self._soledad.load_offline(username, password, uuid)
+ def soledad_get_service_token(self, service):
+ """
+ Attempt to get an authentication token for a given service.
+ """
+ self._soledad.get_service_token(service)
+
def soledad_cancel_bootstrap(self):
"""
Cancel the ongoing soledad bootstrapping process (if any).
diff --git a/src/leap/bitmask/backend/leapsignaler.py b/src/leap/bitmask/backend/leapsignaler.py
index 1ac51f5e..13a9fa5f 100644
--- a/src/leap/bitmask/backend/leapsignaler.py
+++ b/src/leap/bitmask/backend/leapsignaler.py
@@ -97,6 +97,7 @@ class LeapSignaler(SignalerQt):
soledad_offline_finished = QtCore.Signal()
soledad_password_change_error = QtCore.Signal()
soledad_password_change_ok = QtCore.Signal()
+ soledad_got_service_token = QtCore.Signal(object)
srp_auth_bad_user_or_password = QtCore.Signal()
srp_auth_connection_error = QtCore.Signal()
diff --git a/src/leap/bitmask/gui/mainwindow.py b/src/leap/bitmask/gui/mainwindow.py
index a8a4e41d..189a6295 100644
--- a/src/leap/bitmask/gui/mainwindow.py
+++ b/src/leap/bitmask/gui/mainwindow.py
@@ -407,6 +407,10 @@ class MainWindow(QtGui.QMainWindow, SignalTracker):
sig.soledad_invalid_auth_token.connect(
self._mail_status.set_soledad_invalid_auth_token)
+ self._service_tokens = {}
+ sig.soledad_got_service_token.connect(
+ self._set_service_tokens)
+
# TODO: connect this with something
# sig.soledad_cancelled_bootstrap.connect()
@@ -1033,6 +1037,13 @@ class MainWindow(QtGui.QMainWindow, SignalTracker):
msg = msg.format(ver=VERSION, ver_hash=VERSION_HASH[:10], greet=greet)
QtGui.QMessageBox.about(self, title, msg)
+ def _set_service_tokens(self, data):
+ """
+ Set the received service token.
+ """
+ service, token = data
+ self._service_tokens[service] = token
+
def _help(self):
"""
TRIGGERS:
@@ -1063,7 +1074,12 @@ class MainWindow(QtGui.QMainWindow, SignalTracker):
manual_imap = self.tr("IMAP: localhost, port {0}".format(IMAP_PORT))
manual_smtp = self.tr("SMTP: localhost, port {0}".format(smtp_port))
manual_username = self.tr("Username: your full email address")
- manual_password = self.tr("Password: any non-empty text")
+
+ # TODO this should be a widget that allows to be copied to the
+ # clipboard.
+ imap_token = (self._service_tokens.get('imap', None)
+ or "??? (log in to unlock)")
+ manual_password = self.tr("Password: ") + "%s" % (imap_token, )
msg = help_url + self.tr(
"
{0}
"
diff --git a/src/leap/bitmask/services/mail/imap.py b/src/leap/bitmask/services/mail/imap.py
index b06c1d4a..54935f8c 100644
--- a/src/leap/bitmask/services/mail/imap.py
+++ b/src/leap/bitmask/services/mail/imap.py
@@ -20,11 +20,14 @@ Initialization of imap service
import os
import sys
+from twisted.python import log
+
from leap.bitmask.logs.utils import get_logger
from leap.mail.constants import INBOX_NAME
from leap.mail.imap.service import imap
from leap.mail.incoming.service import IncomingMail, INCOMING_CHECK_PERIOD
-from twisted.python import log
+from leap.mail.mail import Account
+
logger = get_logger()
@@ -57,11 +60,13 @@ def get_mail_check_period():
return period
-def start_imap_service(*args, **kwargs):
+def start_imap_service(soledad_sessions):
"""
Initializes and run imap service.
- :returns: LeapIMAPFactory instance
+ :returns: the port as returned by the reactor when starts listening, and
+ the factory for the protocol.
+ :rtype: tuple
"""
from leap.bitmask.config import flags
logger.debug('Launching imap service')
@@ -70,10 +75,10 @@ def start_imap_service(*args, **kwargs):
log.startLogging(open(flags.MAIL_LOGFILE, 'w'))
log.startLogging(sys.stdout)
- return imap.run_service(*args, **kwargs)
+ return imap.run_service(soledad_sessions)
-def start_incoming_mail_service(keymanager, soledad, imap_factory, userid):
+def start_incoming_mail_service(keymanager, soledad, userid):
"""
Initalizes and starts the incomming mail service.
@@ -81,19 +86,13 @@ def start_incoming_mail_service(keymanager, soledad, imap_factory, userid):
"""
def setUpIncomingMail(inbox):
incoming_mail = IncomingMail(
- keymanager,
- soledad,
- inbox.collection,
- userid,
+ keymanager, soledad,
+ inbox, userid,
check_period=get_mail_check_period())
return incoming_mail
- # XXX: do I really need to know here how to get a mailbox??
- # XXX: ideally, the parent service in mail would take care of initializing
- # the account, and passing the mailbox to the incoming service.
- # In an even better world, we just would subscribe to a channel that would
- # pass us the serialized object to be inserted.
- acc = imap_factory.theAccount
- d = acc.callWhenReady(lambda _: acc.getMailbox(INBOX_NAME))
+ acc = Account(soledad)
+ d = acc.callWhenReady(lambda _: acc.get_collection_by_mailbox(INBOX_NAME))
d.addCallback(setUpIncomingMail)
+ d.addErrback(log.err)
return d
diff --git a/src/leap/bitmask/services/mail/imapcontroller.py b/src/leap/bitmask/services/mail/imapcontroller.py
index 5053d897..855fb74b 100644
--- a/src/leap/bitmask/services/mail/imapcontroller.py
+++ b/src/leap/bitmask/services/mail/imapcontroller.py
@@ -60,9 +60,9 @@ class IMAPController(object):
"""
logger.debug('Starting imap service')
+ soledad_sessions = {userid: self._soledad}
self.imap_port, self.imap_factory = imap.start_imap_service(
- self._soledad,
- userid=userid)
+ soledad_sessions)
def start_and_assign_incoming_service(incoming_mail):
# this returns a deferred that will be called when the looping call
@@ -74,9 +74,7 @@ class IMAPController(object):
if offline is False:
d = imap.start_incoming_mail_service(
- self._keymanager,
- self._soledad,
- self.imap_factory,
+ self._keymanager, self._soledad,
userid)
d.addCallback(start_and_assign_incoming_service)
d.addErrback(lambda f: logger.error(f.printTraceback()))
--
cgit v1.2.3
From 7b80dd1fca9828331f3327c418913539a3a303c0 Mon Sep 17 00:00:00 2001
From: Kali Kaneko
Date: Wed, 16 Dec 2015 15:33:25 -0400
Subject: [feat] adapt to use cred-based authentication for smtp
---
changes/next-changelog.rst | 2 ++
src/leap/bitmask/backend/components.py | 14 +++++----
src/leap/bitmask/gui/mainwindow.py | 16 +++++++----
src/leap/bitmask/services/mail/smtpbootstrapper.py | 33 +++++++++++++---------
4 files changed, 40 insertions(+), 25 deletions(-)
diff --git a/changes/next-changelog.rst b/changes/next-changelog.rst
index c359b4e2..64774d30 100644
--- a/changes/next-changelog.rst
+++ b/changes/next-changelog.rst
@@ -13,6 +13,8 @@ Features
- `#7552 `_: Improve UI message and add some margin above the msg box.
- `#7656 `_: Adapt to multi-user aware events.
- `#4469 `_: Display randomly generated service token on the Help Window.
+- Use cred-based authentication on SMTP.
+
- `#1234 `_: Description of the new feature corresponding with issue #1234.
- New feature without related issue number.
diff --git a/src/leap/bitmask/backend/components.py b/src/leap/bitmask/backend/components.py
index a07d3bad..e93ca19f 100644
--- a/src/leap/bitmask/backend/components.py
+++ b/src/leap/bitmask/backend/components.py
@@ -797,16 +797,19 @@ class Soledad(object):
def _set_service_tokens_cb(self, result):
- def register_imap_token(imap_token):
- self._service_tokens['imap'] = imap_token
+ def register_service_token(token, service):
+ self._service_tokens[service] = token
if self._signaler is not None:
self._signaler.signal(
self._signaler.soledad_got_service_token,
- ('imap', imap_token))
+ (service, token))
sol = self._soledad_bootstrapper.soledad
d = sol.get_or_create_service_token('imap')
- d.addCallback(register_imap_token)
+ d.addCallback(register_service_token, 'imap')
+ d.addCallback(
+ lambda _: sol.get_or_create_service_token('smtp'))
+ d.addCallback(register_service_token, 'smtp')
d.addCallback(lambda _: result)
return d
@@ -1035,7 +1038,8 @@ class Mail(object):
"""
return threads.deferToThread(
self._smtp_bootstrapper.start_smtp_service,
- self._keymanager_proxy, full_user_id, download_if_needed)
+ self._soledad_proxy, self._keymanager_proxy, full_user_id,
+ download_if_needed)
def start_imap_service(self, full_user_id, offline=False):
"""
diff --git a/src/leap/bitmask/gui/mainwindow.py b/src/leap/bitmask/gui/mainwindow.py
index 189a6295..759b454f 100644
--- a/src/leap/bitmask/gui/mainwindow.py
+++ b/src/leap/bitmask/gui/mainwindow.py
@@ -1075,11 +1075,14 @@ class MainWindow(QtGui.QMainWindow, SignalTracker):
manual_smtp = self.tr("SMTP: localhost, port {0}".format(smtp_port))
manual_username = self.tr("Username: your full email address")
- # TODO this should be a widget that allows to be copied to the
- # clipboard.
- imap_token = (self._service_tokens.get('imap', None)
- or "??? (log in to unlock)")
- manual_password = self.tr("Password: ") + "%s" % (imap_token, )
+ # FIXME on i3, this doens't allow to mouse-select.
+ # Switch to a dialog in which we can set the QLabel
+ imap_token = (self._service_tokens.get('imap', None) or
+ "??? (log in to unlock)")
+ smtp_token = (self._service_tokens.get('smtp', None) or
+ "??? (log in to unlock)")
+ imap_password = self.tr("IMAP Password:") + " %s" % (imap_token,)
+ smtp_password = self.tr("SMTP Password:") + " %s" % (smtp_token,)
msg = help_url + self.tr(
"
{0}
"
@@ -1090,9 +1093,10 @@ class MainWindow(QtGui.QMainWindow, SignalTracker):
"
{4}
"
"
{5}
"
"
{6}
"
+ "
{7}
"
"
").format(email_quick_reference, thunderbird_text,
manual_text, manual_imap, manual_smtp,
- manual_username, manual_password)
+ manual_username, imap_password, smtp_password)
QtGui.QMessageBox.about(self, self.tr("Bitmask Help"), msg)
def _needs_update(self):
diff --git a/src/leap/bitmask/services/mail/smtpbootstrapper.py b/src/leap/bitmask/services/mail/smtpbootstrapper.py
index a577509e..dadf59dd 100644
--- a/src/leap/bitmask/services/mail/smtpbootstrapper.py
+++ b/src/leap/bitmask/services/mail/smtpbootstrapper.py
@@ -19,6 +19,7 @@ SMTP bootstrapping
"""
import os
import warnings
+from collections import namedtuple
from requests.exceptions import HTTPError
@@ -127,9 +128,6 @@ class SMTPBootstrapper(AbstractBootstrapper):
Start the smtp service using the downloaded configurations.
"""
# TODO Make the encrypted_only configurable
- # TODO pick local smtp port in a better way
- # TODO remove hard-coded port and let leap.mail set
- # the specific default.
# TODO handle more than one host and define how to choose
hosts = self._smtp_config.get_hosts()
hostname = hosts.keys()[0]
@@ -138,19 +136,25 @@ class SMTPBootstrapper(AbstractBootstrapper):
client_cert_path = self._smtp_config.get_client_cert_path(
self._userid, self._provider_config, about_to_download=True)
- from leap.mail.smtp import setup_smtp_gateway
+ # XXX this should be defined in leap.mail.smtp, it's in bitmask.core
+ # right now.
+ SendmailOpts = namedtuple(
+ 'SendmailOpts', ['cert', 'key', 'hostname', 'port'])
- self._smtp_service, self._smtp_port = setup_smtp_gateway(
- port=2013,
- userid=self._userid,
- keymanager=self._keymanager,
- smtp_host=host,
- smtp_port=port,
- smtp_cert=client_cert_path,
- smtp_key=client_cert_path,
- encrypted_only=False)
+ userid = self._userid
+ soledad_sessions = {userid: self._soledad}
+ keymanager_sessions = {userid: self._keymanager}
- def start_smtp_service(self, keymanager, userid, download_if_needed=False):
+ key = cert = client_cert_path
+ opts = SendmailOpts(cert, key, host, port)
+ sendmail_opts = {userid: opts}
+
+ from leap.mail.smtp import run_service
+ self._smtp_service, self._smtp_port = run_service(
+ soledad_sessions, keymanager_sessions, sendmail_opts)
+
+ def start_smtp_service(self, soledad, keymanager, userid,
+ download_if_needed=False):
"""
Starts the SMTP service.
@@ -170,6 +174,7 @@ class SMTPBootstrapper(AbstractBootstrapper):
raise MalformedUserId()
self._provider_config = ProviderConfig.get_provider_config(domain)
+ self._soledad = soledad
self._keymanager = keymanager
self._smtp_config = SMTPConfig()
self._userid = str(userid)
--
cgit v1.2.3
From e847bf6a59783611bf14fa7f480fabe58e0b13dd Mon Sep 17 00:00:00 2001
From: Ruben Pollan
Date: Fri, 18 Dec 2015 13:27:18 +0100
Subject: [bug] run make on bitmask_client when updating docker
---
docker/leap_bootstrap.sh | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/docker/leap_bootstrap.sh b/docker/leap_bootstrap.sh
index 4f553ee7..a717ab6d 100755
--- a/docker/leap_bootstrap.sh
+++ b/docker/leap_bootstrap.sh
@@ -271,6 +271,10 @@ EOF
install_dependencies
setup_develop
+ cd $REPOS_ROOT/bitmask_client/
+ make
+ cd -
+
set +x
echo "${cc_green}Status: $status done!${cc_normal}"
}
--
cgit v1.2.3
From fa05e417d58f1cec68a78e235989f01181f9632f Mon Sep 17 00:00:00 2001
From: PaixuAabuizia
Date: Sun, 24 Jan 2016 14:48:48 +0100
Subject: [bug] change backend process spawn method
the original implementation causes problems in win32 (see #7240) possibly because pyinstaller cannot resolve the lambda correctly. using the documented multiprocessing.Process approach to pass parameters works here
---
src/leap/bitmask/app.py | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/src/leap/bitmask/app.py b/src/leap/bitmask/app.py
index a1b7481a..982d8a13 100644
--- a/src/leap/bitmask/app.py
+++ b/src/leap/bitmask/app.py
@@ -223,9 +223,9 @@ def start_app():
backend_pid = None
if not backend_running:
frontend_pid = os.getpid()
- backend = lambda: run_backend(opts.danger, flags_dict, frontend_pid)
- backend_process = multiprocessing.Process(target=backend,
- name='Backend')
+ backend_process = multiprocessing.Process(target=run_backend,
+ name='Backend',
+ args=(opts.danger, flags_dict, frontend_pid))
# we don't set the 'daemon mode' since we need to start child processes
# in the backend
# backend_process.daemon = True
--
cgit v1.2.3
From 449de440ae1d3e533291ff6a2f41edd702c7746a Mon Sep 17 00:00:00 2001
From: PaixuAabuizia
Date: Wed, 3 Feb 2016 11:59:52 +0100
Subject: [bug] frozen backend fails to spawn on windows
according to [1] the backend should raise a Runtime Error, instead what happens is that the process is spawned again and again but never runs actual code.
[1] https://docs.python.org/2.7/library/multiprocessing.html#multiprocessing.freeze_support
---
src/leap/bitmask/app.py | 1 +
1 file changed, 1 insertion(+)
diff --git a/src/leap/bitmask/app.py b/src/leap/bitmask/app.py
index 982d8a13..dc1ee6df 100644
--- a/src/leap/bitmask/app.py
+++ b/src/leap/bitmask/app.py
@@ -237,4 +237,5 @@ def start_app():
if __name__ == "__main__":
+ multiprocessing.freeze_support()
start_app()
--
cgit v1.2.3
From 8e17fb43b4cbda9ee7b386d084e01fc99345f060 Mon Sep 17 00:00:00 2001
From: Ruben Pollan
Date: Mon, 21 Dec 2015 15:48:00 +0100
Subject: [feat] use fingerprint instead of key_id to address keys
---
src/leap/bitmask/backend/components.py | 3 ++-
src/leap/bitmask/gui/advanced_key_management.py | 3 ++-
2 files changed, 4 insertions(+), 2 deletions(-)
diff --git a/src/leap/bitmask/backend/components.py b/src/leap/bitmask/backend/components.py
index e93ca19f..d8e4edbf 100644
--- a/src/leap/bitmask/backend/components.py
+++ b/src/leap/bitmask/backend/components.py
@@ -984,7 +984,8 @@ class Keymanager(object):
List all the keys stored in the local DB.
"""
def signal_details(public_key):
- details = (public_key.key_id, public_key.fingerprint)
+ # XXX: We should avoid the key-id
+ details = (public_key.fingerprint[-16:], public_key.fingerprint)
self._signaler.signal(self._signaler.keymanager_key_details,
details)
diff --git a/src/leap/bitmask/gui/advanced_key_management.py b/src/leap/bitmask/gui/advanced_key_management.py
index 2e315d18..bc496a57 100644
--- a/src/leap/bitmask/gui/advanced_key_management.py
+++ b/src/leap/bitmask/gui/advanced_key_management.py
@@ -94,6 +94,7 @@ class AdvancedKeyManagement(QtGui.QDialog):
"""
Set the current user's key details into the gui.
"""
+ # XXX: We should avoid the key-id
self.ui.leKeyID.setText(details[0])
self.ui.leFingerprint.setText(details[1])
@@ -246,7 +247,7 @@ class AdvancedKeyManagement(QtGui.QDialog):
row = keys_table.rowCount()
keys_table.insertRow(row)
keys_table.setItem(row, 0, QtGui.QTableWidgetItem(key.address))
- keys_table.setItem(row, 1, QtGui.QTableWidgetItem(key.key_id))
+ keys_table.setItem(row, 1, QtGui.QTableWidgetItem(key.fingerprint))
def _backend_connect(self):
"""
--
cgit v1.2.3
From 9a658c81619af892a4b29e0122cd1c1ba2e428e4 Mon Sep 17 00:00:00 2001
From: Kali Kaneko
Date: Fri, 4 Mar 2016 11:27:55 -0400
Subject: [pkg] move to versioneer 0.15
---
.gitattributes | 1 +
MANIFEST.in | 1 +
setup.cfg | 7 +
setup.py | 15 +-
src/leap/bitmask/__init__.py | 50 +-
src/leap/bitmask/_version.py | 553 ++++++++----
versioneer.py | 1978 ++++++++++++++++++++++++++++++++----------
7 files changed, 1933 insertions(+), 672 deletions(-)
diff --git a/.gitattributes b/.gitattributes
index eb8672e0..2b5f09d8 100644
--- a/.gitattributes
+++ b/.gitattributes
@@ -17,3 +17,4 @@ share/ export-ignore
src/leap.egg-info/ export-ignore
src/leap_client.egg-info export-ignore
src/leap/_version.py export-subst
+src/leap/bitmask/_version.py export-subst
diff --git a/MANIFEST.in b/MANIFEST.in
index 73355b99..5f1fc00a 100644
--- a/MANIFEST.in
+++ b/MANIFEST.in
@@ -12,3 +12,4 @@ include src/leap/bitmask/crypto/tests/wrongcert.pem
include src/leap/bitmask/gui/ui_*.py
include src/leap/bitmask/gui/*_rc.py
+include src/leap/bitmask/_version.py
diff --git a/setup.cfg b/setup.cfg
index 1a05d2c3..7732c1cc 100644
--- a/setup.cfg
+++ b/setup.cfg
@@ -14,3 +14,10 @@ exclude = *_rc.py,ui_*,_version.py,docker,build,docs,pkg,versioneer.py,_binaries
[flake8]
ignore = E731
exclude = *_rc.py,ui_*,_version.py,docker,build,docs,pkg,versioneer.py,_binaries.py
+
+[versioneer]
+VCS = git
+style = pep440
+versionfile_source = src/leap/bitmask/_version.py
+versionfile_build = leap/bitmask/_version.py
+tag_prefix =
diff --git a/setup.py b/setup.py
index 8463c172..e85c4564 100755
--- a/setup.py
+++ b/setup.py
@@ -41,10 +41,6 @@ except ImportError:
from pkg import utils
import versioneer
-versioneer.versionfile_source = 'src/leap/bitmask/_version.py'
-versioneer.versionfile_build = 'leap/bitmask/_version.py'
-versioneer.tag_prefix = '' # tags are like 1.2.0
-versioneer.parentdir_prefix = 'leap.bitmask-'
# The following import avoids the premature unloading of the `util` submodule
@@ -78,7 +74,7 @@ DOWNLOAD_BASE = ('https://github.com/leapcode/bitmask_client/'
'archive/%s.tar.gz')
_versions = versioneer.get_versions()
VERSION = _versions['version']
-VERSION_FULL = _versions['full']
+VERSION_REVISION = _versions['full-revisionid']
DOWNLOAD_URL = ""
# get the short version for the download url
@@ -108,12 +104,13 @@ class freeze_debianver(Command):
# of this file.
version_version = '{version}'
-version_full = '{version_full}'
+version_revisionid = '{version_revision}'
"""
templatefun = r"""
def get_versions(default={}, verbose=False):
- return {'version': version_version, 'full': version_full}
+ return {'version': version_version,
+ 'full-revisionid': version_revisionid}
"""
def initialize_options(self):
@@ -130,7 +127,7 @@ def get_versions(default={}, verbose=False):
return
subst_template = self.template.format(
version=VERSION_SHORT,
- version_full=VERSION_FULL) + self.templatefun
+ version_full=VERSION_REVISION) + self.templatefun
with open(versioneer.versionfile_source, 'w') as f:
f.write(subst_template)
@@ -264,7 +261,7 @@ cmdclass["hash_binaries"] = cmd_binary_hash
# next two classes need to augment the versioneer modified ones
-versioneer_build = cmdclass['build']
+versioneer_build = cmdclass['build_py']
versioneer_sdist = cmdclass['sdist']
diff --git a/src/leap/bitmask/__init__.py b/src/leap/bitmask/__init__.py
index 9ec5aae7..966ce91e 100644
--- a/src/leap/bitmask/__init__.py
+++ b/src/leap/bitmask/__init__.py
@@ -19,12 +19,6 @@ Init file for leap.bitmask
Initializes version and app info.
"""
-import re
-
-from pkg_resources import parse_version
-
-from leap.bitmask.util import first
-
# HACK: This is a hack so that py2app copies _scrypt.so to the right
# place, it can't be technically imported, but that doesn't matter
# because the import is never executed
@@ -32,7 +26,7 @@ if False:
import _scrypt # noqa - skip 'not used' warning
-def _is_release_version(version):
+def _is_release_version(version_str):
"""
Helper to determine whether a version is a final release or not.
The release needs to be of the form: w.x.y.z containing only numbers
@@ -43,40 +37,12 @@ def _is_release_version(version):
:returns: if the version is a release version or not.
:rtype: bool
"""
- parsed_version = parse_version(version)
- not_number = 0
- for x in parsed_version:
- try:
- int(x)
- except:
- not_number += 1
-
- return not_number == 1
-
-
-__version__ = "unknown"
-IS_RELEASE_VERSION = False
-
-__short_version__ = "unknown"
-
-try:
- from leap.bitmask._version import get_versions
- __version__ = get_versions()['version']
- __version_hash__ = get_versions()['full']
- IS_RELEASE_VERSION = _is_release_version(__version__)
- del get_versions
-except ImportError:
- # running on a tree that has not run
- # the setup.py setver
- pass
+ parts = __version__.split('.')
+ patch = parts[2]
+ return patch.isdigit()
-__appname__ = "unknown"
-try:
- from leap.bitmask._appname import __appname__
-except ImportError:
- # running on a tree that has not run
- # the setup.py setver
- pass
-__short_version__ = first(re.findall('\d+\.\d+\.\d+', __version__))
-__full_version__ = __appname__ + '/' + str(__version__)
+from ._version import get_versions
+__version__ = get_versions()['version']
+IS_RELEASE_VERSION = _is_release_version(__version__)
+del get_versions
diff --git a/src/leap/bitmask/_version.py b/src/leap/bitmask/_version.py
index 412b0c9e..93700af1 100644
--- a/src/leap/bitmask/_version.py
+++ b/src/leap/bitmask/_version.py
@@ -1,201 +1,460 @@
-IN_LONG_VERSION_PY = True
# This file helps to compute a version number in source trees obtained from
# git-archive tarball (such as those provided by githubs download-from-tag
-# feature). Distribution tarballs (build by setup.py sdist) and build
+# feature). Distribution tarballs (built by setup.py sdist) and build
# directories (produced by setup.py build) will contain a much shorter file
# that just contains the computed version number.
# This file is released into the public domain. Generated by
-# versioneer-0.7+ (https://github.com/warner/python-versioneer)
-
-# these strings will be replaced by git during git-archive
-git_refnames = "$Format:%d$"
-git_full = "$Format:%H$"
-
+# versioneer-0.15 (https://github.com/warner/python-versioneer)
+import errno
+import os
+import re
import subprocess
import sys
-import re
-import os.path
-def run_command(args, cwd=None, verbose=False):
- try:
- # remember shell=False, so use git.cmd on windows, not just git
- p = subprocess.Popen(args, stdout=subprocess.PIPE, cwd=cwd)
- except EnvironmentError:
- e = sys.exc_info()[1]
+def get_keywords():
+ # these strings will be replaced by git during git-archive.
+ # setup.py/versioneer.py will grep for the variable names, so they must
+ # each be defined on a line of their own. _version.py will just call
+ # get_keywords().
+ git_refnames = "$Format:%d$"
+ git_full = "$Format:%H$"
+ keywords = {"refnames": git_refnames, "full": git_full}
+ return keywords
+
+
+class VersioneerConfig:
+ pass
+
+
+def get_config():
+ # these strings are filled in when 'setup.py versioneer' creates
+ # _version.py
+ cfg = VersioneerConfig()
+ cfg.VCS = "git"
+ cfg.style = "pep440"
+ cfg.tag_prefix = ""
+ cfg.parentdir_prefix = "None"
+ cfg.versionfile_source = "src/leap/bitmask/_version.py"
+ cfg.verbose = False
+ return cfg
+
+
+class NotThisMethod(Exception):
+ pass
+
+
+LONG_VERSION_PY = {}
+HANDLERS = {}
+
+
+def register_vcs_handler(vcs, method): # decorator
+ def decorate(f):
+ if vcs not in HANDLERS:
+ HANDLERS[vcs] = {}
+ HANDLERS[vcs][method] = f
+ return f
+ return decorate
+
+
+def run_command(commands, args, cwd=None, verbose=False, hide_stderr=False):
+ assert isinstance(commands, list)
+ p = None
+ for c in commands:
+ try:
+ dispcmd = str([c] + args)
+ # remember shell=False, so use git.cmd on windows, not just git
+ p = subprocess.Popen([c] + args, cwd=cwd, stdout=subprocess.PIPE,
+ stderr=(subprocess.PIPE if hide_stderr
+ else None))
+ break
+ except EnvironmentError:
+ e = sys.exc_info()[1]
+ if e.errno == errno.ENOENT:
+ continue
+ if verbose:
+ print("unable to run %s" % dispcmd)
+ print(e)
+ return None
+ else:
if verbose:
- print("unable to run %s" % args[0])
- print(e)
+ print("unable to find command, tried %s" % (commands,))
return None
stdout = p.communicate()[0].strip()
- if sys.version >= '3':
+ if sys.version_info[0] >= 3:
stdout = stdout.decode()
if p.returncode != 0:
if verbose:
- print("unable to run %s (error)" % args[0])
+ print("unable to run %s (error)" % dispcmd)
return None
return stdout
-def get_expanded_variables(versionfile_source):
+def versions_from_parentdir(parentdir_prefix, root, verbose):
+ # Source tarballs conventionally unpack into a directory that includes
+ # both the project name and a version string.
+ dirname = os.path.basename(root)
+ if not dirname.startswith(parentdir_prefix):
+ if verbose:
+ print("guessing rootdir is '%s', but '%s' doesn't start with "
+ "prefix '%s'" % (root, dirname, parentdir_prefix))
+ raise NotThisMethod("rootdir doesn't start with parentdir_prefix")
+ return {"version": dirname[len(parentdir_prefix):],
+ "full-revisionid": None,
+ "dirty": False, "error": None}
+
+
+@register_vcs_handler("git", "get_keywords")
+def git_get_keywords(versionfile_abs):
# the code embedded in _version.py can just fetch the value of these
- # variables. When used from setup.py, we don't want to import
- # _version.py, so we do it with a regexp instead. This function is not
- # used from _version.py.
- variables = {}
+ # keywords. When used from setup.py, we don't want to import _version.py,
+ # so we do it with a regexp instead. This function is not used from
+ # _version.py.
+ keywords = {}
try:
- for line in open(versionfile_source, "r").readlines():
+ f = open(versionfile_abs, "r")
+ for line in f.readlines():
if line.strip().startswith("git_refnames ="):
mo = re.search(r'=\s*"(.*)"', line)
if mo:
- variables["refnames"] = mo.group(1)
+ keywords["refnames"] = mo.group(1)
if line.strip().startswith("git_full ="):
mo = re.search(r'=\s*"(.*)"', line)
if mo:
- variables["full"] = mo.group(1)
+ keywords["full"] = mo.group(1)
+ f.close()
except EnvironmentError:
pass
- return variables
+ return keywords
-def versions_from_expanded_variables(variables, tag_prefix, verbose=False):
- refnames = variables["refnames"].strip()
+@register_vcs_handler("git", "keywords")
+def git_versions_from_keywords(keywords, tag_prefix, verbose):
+ if not keywords:
+ raise NotThisMethod("no keywords at all, weird")
+ refnames = keywords["refnames"].strip()
if refnames.startswith("$Format"):
if verbose:
- print("variables are unexpanded, not using")
- return {} # unexpanded, so not in an unpacked git-archive tarball
+ print("keywords are unexpanded, not using")
+ raise NotThisMethod("unexpanded keywords, not a git-archive tarball")
refs = set([r.strip() for r in refnames.strip("()").split(",")])
- for ref in list(refs):
- if not re.search(r'\d', ref):
- if verbose:
- print("discarding '%s', no digits" % ref)
- refs.discard(ref)
- # Assume all version tags have a digit. git's %d expansion
- # behaves like git log --decorate=short and strips out the
- # refs/heads/ and refs/tags/ prefixes that would let us
- # distinguish between branches and tags. By ignoring refnames
- # without digits, we filter out many common branch names like
- # "release" and "stabilization", as well as "HEAD" and "master".
+ # starting in git-1.8.3, tags are listed as "tag: foo-1.0" instead of
+ # just "foo-1.0". If we see a "tag: " prefix, prefer those.
+ TAG = "tag: "
+ tags = set([r[len(TAG):] for r in refs if r.startswith(TAG)])
+ if not tags:
+ # Either we're using git < 1.8.3, or there really are no tags. We use
+ # a heuristic: assume all version tags have a digit. The old git %d
+ # expansion behaves like git log --decorate=short and strips out the
+ # refs/heads/ and refs/tags/ prefixes that would let us distinguish
+ # between branches and tags. By ignoring refnames without digits, we
+ # filter out many common branch names like "release" and
+ # "stabilization", as well as "HEAD" and "master".
+ tags = set([r for r in refs if re.search(r'\d', r)])
+ if verbose:
+ print("discarding '%s', no digits" % ",".join(refs-tags))
if verbose:
- print("remaining refs: %s" % ",".join(sorted(refs)))
- for ref in sorted(refs):
+ print("likely tags: %s" % ",".join(sorted(tags)))
+ for ref in sorted(tags):
# sorting will prefer e.g. "2.0" over "2.0rc1"
if ref.startswith(tag_prefix):
r = ref[len(tag_prefix):]
if verbose:
print("picking %s" % r)
return {"version": r,
- "full": variables["full"].strip()}
- # no suitable tags, so we use the full revision id
+ "full-revisionid": keywords["full"].strip(),
+ "dirty": False, "error": None
+ }
+ # no suitable tags, so version is "0+unknown", but full hex is still there
if verbose:
- print("no suitable tags, using full revision id")
- return {"version": variables["full"].strip(),
- "full": variables["full"].strip()}
-
-
-def versions_from_vcs(tag_prefix, versionfile_source, verbose=False):
- # this runs 'git' from the root of the source tree. That either means
- # someone ran a setup.py command (and this code is in versioneer.py, so
- # IN_LONG_VERSION_PY=False, thus the containing directory is the root of
- # the source tree), or someone ran a project-specific entry point (and
- # this code is in _version.py, so IN_LONG_VERSION_PY=True, thus the
- # containing directory is somewhere deeper in the source tree). This only
- # gets called if the git-archive 'subst' variables were *not* expanded,
- # and _version.py hasn't already been rewritten with a short version
- # string, meaning we're inside a checked out source tree.
+ print("no suitable tags, using unknown + full revision id")
+ return {"version": "0+unknown",
+ "full-revisionid": keywords["full"].strip(),
+ "dirty": False, "error": "no suitable tags"}
+
+
+@register_vcs_handler("git", "pieces_from_vcs")
+def git_pieces_from_vcs(tag_prefix, root, verbose, run_command=run_command):
+ # this runs 'git' from the root of the source tree. This only gets called
+ # if the git-archive 'subst' keywords were *not* expanded, and
+ # _version.py hasn't already been rewritten with a short version string,
+ # meaning we're inside a checked out source tree.
- try:
- here = os.path.abspath(__file__)
- except NameError:
- # some py2exe/bbfreeze/non-CPython implementations don't do __file__
- return {} # not always correct
-
- # versionfile_source is the relative path from the top of the source tree
- # (where the .git directory might live) to this file. Invert this to find
- # the root from __file__.
- root = here
- if IN_LONG_VERSION_PY:
- for i in range(len(versionfile_source.split("/"))):
- root = os.path.dirname(root)
- else:
- root = os.path.dirname(here)
if not os.path.exists(os.path.join(root, ".git")):
if verbose:
print("no .git in %s" % root)
- return {}
+ raise NotThisMethod("no .git directory")
- GIT = "git"
+ GITS = ["git"]
if sys.platform == "win32":
- GIT = "git.cmd"
- stdout = run_command([GIT, "describe", "--tags", "--dirty", "--always"],
- cwd=root)
- if stdout is None:
- return {}
- if not stdout.startswith(tag_prefix):
- if verbose:
- print("tag '%s' doesn't start with prefix '%s'" % (
- stdout, tag_prefix))
- return {}
- tag = stdout[len(tag_prefix):]
- stdout = run_command([GIT, "rev-parse", "HEAD"], cwd=root)
- if stdout is None:
- return {}
- full = stdout.strip()
- if tag.endswith("-dirty"):
- full += "-dirty"
- return {"version": tag, "full": full}
-
-
-def versions_from_parentdir(parentdir_prefix, versionfile_source,
- verbose=False):
- if IN_LONG_VERSION_PY:
- # We're running from _version.py. If it's from a source tree
- # (execute-in-place), we can work upwards to find the root of the
- # tree, and then check the parent directory for a version string. If
- # it's in an installed application, there's no hope.
- try:
- here = os.path.abspath(__file__)
- except NameError:
- # py2exe/bbfreeze/non-CPython don't have __file__
- return {} # without __file__, we have no hope
+ GITS = ["git.cmd", "git.exe"]
+ # if there is a tag, this yields TAG-NUM-gHEX[-dirty]
+ # if there are no tags, this yields HEX[-dirty] (no NUM)
+ describe_out = run_command(GITS, ["describe", "--tags", "--dirty",
+ "--always", "--long"],
+ cwd=root)
+ # --long was added in git-1.5.5
+ if describe_out is None:
+ raise NotThisMethod("'git describe' failed")
+ describe_out = describe_out.strip()
+ full_out = run_command(GITS, ["rev-parse", "HEAD"], cwd=root)
+ if full_out is None:
+ raise NotThisMethod("'git rev-parse' failed")
+ full_out = full_out.strip()
+
+ pieces = {}
+ pieces["long"] = full_out
+ pieces["short"] = full_out[:7] # maybe improved later
+ pieces["error"] = None
+
+ # parse describe_out. It will be like TAG-NUM-gHEX[-dirty] or HEX[-dirty]
+ # TAG might have hyphens.
+ git_describe = describe_out
+
+ # look for -dirty suffix
+ dirty = git_describe.endswith("-dirty")
+ pieces["dirty"] = dirty
+ if dirty:
+ git_describe = git_describe[:git_describe.rindex("-dirty")]
+
+ # now we have TAG-NUM-gHEX or HEX
+
+ if "-" in git_describe:
+ # TAG-NUM-gHEX
+ mo = re.search(r'^(.+)-(\d+)-g([0-9a-f]+)$', git_describe)
+ if not mo:
+ # unparseable. Maybe git-describe is misbehaving?
+ pieces["error"] = ("unable to parse git-describe output: '%s'"
+ % describe_out)
+ return pieces
+
+ # tag
+ full_tag = mo.group(1)
+ if not full_tag.startswith(tag_prefix):
+ if verbose:
+ fmt = "tag '%s' doesn't start with prefix '%s'"
+ print(fmt % (full_tag, tag_prefix))
+ pieces["error"] = ("tag '%s' doesn't start with prefix '%s'"
+ % (full_tag, tag_prefix))
+ return pieces
+ pieces["closest-tag"] = full_tag[len(tag_prefix):]
+
+ # distance: number of commits since tag
+ pieces["distance"] = int(mo.group(2))
+
+ # commit: short hex revision ID
+ pieces["short"] = mo.group(3)
+
+ else:
+ # HEX: no tags
+ pieces["closest-tag"] = None
+ count_out = run_command(GITS, ["rev-list", "HEAD", "--count"],
+ cwd=root)
+ pieces["distance"] = int(count_out) # total number of commits
+
+ return pieces
+
+
+def plus_or_dot(pieces):
+ if "+" in pieces.get("closest-tag", ""):
+ return "."
+ return "+"
+
+
+def render_pep440(pieces):
+ # now build up version string, with post-release "local version
+ # identifier". Our goal: TAG[+DISTANCE.gHEX[.dirty]] . Note that if you
+ # get a tagged build and then dirty it, you'll get TAG+0.gHEX.dirty
+
+ # exceptions:
+ # 1: no tags. git_describe was just HEX. 0+untagged.DISTANCE.gHEX[.dirty]
+
+ if pieces["closest-tag"]:
+ rendered = pieces["closest-tag"]
+ if pieces["distance"] or pieces["dirty"]:
+ rendered += plus_or_dot(pieces)
+ rendered += "%d.g%s" % (pieces["distance"], pieces["short"])
+ if pieces["dirty"]:
+ rendered += ".dirty"
+ else:
+ # exception #1
+ rendered = "0+untagged.%d.g%s" % (pieces["distance"],
+ pieces["short"])
+ if pieces["dirty"]:
+ rendered += ".dirty"
+ return rendered
+
+
+def render_pep440_pre(pieces):
+ # TAG[.post.devDISTANCE] . No -dirty
+
+ # exceptions:
+ # 1: no tags. 0.post.devDISTANCE
+
+ if pieces["closest-tag"]:
+ rendered = pieces["closest-tag"]
+ if pieces["distance"]:
+ rendered += ".post.dev%d" % pieces["distance"]
+ else:
+ # exception #1
+ rendered = "0.post.dev%d" % pieces["distance"]
+ return rendered
+
+
+def render_pep440_post(pieces):
+ # TAG[.postDISTANCE[.dev0]+gHEX] . The ".dev0" means dirty. Note that
+ # .dev0 sorts backwards (a dirty tree will appear "older" than the
+ # corresponding clean one), but you shouldn't be releasing software with
+ # -dirty anyways.
+
+ # exceptions:
+ # 1: no tags. 0.postDISTANCE[.dev0]
+
+ if pieces["closest-tag"]:
+ rendered = pieces["closest-tag"]
+ if pieces["distance"] or pieces["dirty"]:
+ rendered += ".post%d" % pieces["distance"]
+ if pieces["dirty"]:
+ rendered += ".dev0"
+ rendered += plus_or_dot(pieces)
+ rendered += "g%s" % pieces["short"]
+ else:
+ # exception #1
+ rendered = "0.post%d" % pieces["distance"]
+ if pieces["dirty"]:
+ rendered += ".dev0"
+ rendered += "+g%s" % pieces["short"]
+ return rendered
+
+
+def render_pep440_old(pieces):
+ # TAG[.postDISTANCE[.dev0]] . The ".dev0" means dirty.
+
+ # exceptions:
+ # 1: no tags. 0.postDISTANCE[.dev0]
+
+ if pieces["closest-tag"]:
+ rendered = pieces["closest-tag"]
+ if pieces["distance"] or pieces["dirty"]:
+ rendered += ".post%d" % pieces["distance"]
+ if pieces["dirty"]:
+ rendered += ".dev0"
+ else:
+ # exception #1
+ rendered = "0.post%d" % pieces["distance"]
+ if pieces["dirty"]:
+ rendered += ".dev0"
+ return rendered
+
+
+def render_git_describe(pieces):
+ # TAG[-DISTANCE-gHEX][-dirty], like 'git describe --tags --dirty
+ # --always'
+
+ # exceptions:
+ # 1: no tags. HEX[-dirty] (note: no 'g' prefix)
+
+ if pieces["closest-tag"]:
+ rendered = pieces["closest-tag"]
+ if pieces["distance"]:
+ rendered += "-%d-g%s" % (pieces["distance"], pieces["short"])
+ else:
+ # exception #1
+ rendered = pieces["short"]
+ if pieces["dirty"]:
+ rendered += "-dirty"
+ return rendered
+
+
+def render_git_describe_long(pieces):
+ # TAG-DISTANCE-gHEX[-dirty], like 'git describe --tags --dirty
+ # --always -long'. The distance/hash is unconditional.
+
+ # exceptions:
+ # 1: no tags. HEX[-dirty] (note: no 'g' prefix)
+
+ if pieces["closest-tag"]:
+ rendered = pieces["closest-tag"]
+ rendered += "-%d-g%s" % (pieces["distance"], pieces["short"])
+ else:
+ # exception #1
+ rendered = pieces["short"]
+ if pieces["dirty"]:
+ rendered += "-dirty"
+ return rendered
+
+
+def render(pieces, style):
+ if pieces["error"]:
+ return {"version": "unknown",
+ "full-revisionid": pieces.get("long"),
+ "dirty": None,
+ "error": pieces["error"]}
+
+ if not style or style == "default":
+ style = "pep440" # the default
+
+ if style == "pep440":
+ rendered = render_pep440(pieces)
+ elif style == "pep440-pre":
+ rendered = render_pep440_pre(pieces)
+ elif style == "pep440-post":
+ rendered = render_pep440_post(pieces)
+ elif style == "pep440-old":
+ rendered = render_pep440_old(pieces)
+ elif style == "git-describe":
+ rendered = render_git_describe(pieces)
+ elif style == "git-describe-long":
+ rendered = render_git_describe_long(pieces)
+ else:
+ raise ValueError("unknown style '%s'" % style)
+
+ return {"version": rendered, "full-revisionid": pieces["long"],
+ "dirty": pieces["dirty"], "error": None}
+
+
+def get_versions():
+ # I am in _version.py, which lives at ROOT/VERSIONFILE_SOURCE. If we have
+ # __file__, we can work backwards from there to the root. Some
+ # py2exe/bbfreeze/non-CPython implementations don't do __file__, in which
+ # case we can only use expanded keywords.
+
+ cfg = get_config()
+ verbose = cfg.verbose
+
+ try:
+ return git_versions_from_keywords(get_keywords(), cfg.tag_prefix,
+ verbose)
+ except NotThisMethod:
+ pass
+
+ try:
+ root = os.path.realpath(__file__)
# versionfile_source is the relative path from the top of the source
- # tree to _version.py. Invert this to find the root from __file__.
- root = here
- for i in range(len(versionfile_source.split("/"))):
+ # tree (where the .git directory might live) to this file. Invert
+ # this to find the root from __file__.
+ for i in cfg.versionfile_source.split('/'):
root = os.path.dirname(root)
- else:
- # we're running from versioneer.py, which means we're running from
- # the setup.py in a source tree. sys.argv[0] is setup.py in the root.
- here = os.path.abspath(sys.argv[0])
- root = os.path.dirname(here)
+ except NameError:
+ return {"version": "0+unknown", "full-revisionid": None,
+ "dirty": None,
+ "error": "unable to find root of source tree"}
- # Source tarballs conventionally unpack into a directory that includes
- # both the project name and a version string.
- dirname = os.path.basename(root)
- if not dirname.startswith(parentdir_prefix):
- if verbose:
- print("guessing rootdir is '%s', but '%s' "
- "doesn't start with prefix '%s'" %
- (root, dirname, parentdir_prefix))
- return None
- return {"version": dirname[len(parentdir_prefix):], "full": ""}
-
-tag_prefix = ""
-parentdir_prefix = "bitmask-"
-versionfile_source = "src/leap/bitmask/_version.py"
-
-
-def get_versions(default={"version": "unknown", "full": ""}, verbose=False):
- variables = {"refnames": git_refnames, "full": git_full}
- ver = versions_from_expanded_variables(variables, tag_prefix, verbose)
- if not ver:
- ver = versions_from_vcs(tag_prefix, versionfile_source, verbose)
- if not ver:
- ver = versions_from_parentdir(parentdir_prefix, versionfile_source,
- verbose)
- if not ver:
- ver = default
- return ver
+ try:
+ pieces = git_pieces_from_vcs(cfg.tag_prefix, root, verbose)
+ return render(pieces, cfg.style)
+ except NotThisMethod:
+ pass
+
+ try:
+ if cfg.parentdir_prefix:
+ return versions_from_parentdir(cfg.parentdir_prefix, root, verbose)
+ except NotThisMethod:
+ pass
+
+ return {"version": "0+unknown", "full-revisionid": None,
+ "dirty": None,
+ "error": "unable to compute version"}
diff --git a/versioneer.py b/versioneer.py
index 885ebcfd..c010f63e 100644
--- a/versioneer.py
+++ b/versioneer.py
@@ -1,170 +1,611 @@
-#! /usr/bin/python
-"""versioneer.py
+# Version: 0.15
-(like a rocketeer, but for versions)
+"""
+The Versioneer
+==============
+* like a rocketeer, but for versions!
* https://github.com/warner/python-versioneer
* Brian Warner
* License: Public Domain
-* Version: 0.7+
-
-This file helps distutils-based projects manage their version number by just
-creating version-control tags.
-
-For developers who work from a VCS-generated tree (e.g. 'git clone' etc),
-each 'setup.py version', 'setup.py build', 'setup.py sdist' will compute a
-version number by asking your version-control tool about the current
-checkout. The version number will be written into a generated _version.py
-file of your choosing, where it can be included by your __init__.py
-
-For users who work from a VCS-generated tarball (e.g. 'git archive'), it will
-compute a version number by looking at the name of the directory created when
-te tarball is unpacked. This conventionally includes both the name of the
-project and a version number.
-
-For users who work from a tarball built by 'setup.py sdist', it will get a
-version number from a previously-generated _version.py file.
-
-As a result, loading code directly from the source tree will not result in a
-real version. If you want real versions from VCS trees (where you frequently
-update from the upstream repository, or do new development), you will need to
-do a 'setup.py version' after each update, and load code from the build/
-directory.
-
-You need to provide this code with a few configuration values:
-
- versionfile_source:
- A project-relative pathname into which the generated version strings
- should be written. This is usually a _version.py next to your project's
- main __init__.py file. If your project uses src/myproject/__init__.py,
- this should be 'src/myproject/_version.py'. This file should be checked
- in to your VCS as usual: the copy created below by 'setup.py
- update_files' will include code that parses expanded VCS keywords in
- generated tarballs. The 'build' and 'sdist' commands will replace it with
- a copy that has just the calculated version string.
-
- versionfile_build:
- Like versionfile_source, but relative to the build directory instead of
- the source directory. These will differ when your setup.py uses
- 'package_dir='. If you have package_dir={'myproject': 'src/myproject'},
- then you will probably have versionfile_build='myproject/_version.py' and
- versionfile_source='src/myproject/_version.py'.
-
- tag_prefix: a string, like 'PROJECTNAME-', which appears at the start of all
- VCS tags. If your tags look like 'myproject-1.2.0', then you
- should use tag_prefix='myproject-'. If you use unprefixed tags
- like '1.2.0', this should be an empty string.
-
- parentdir_prefix: a string, frequently the same as tag_prefix, which
- appears at the start of all unpacked tarball filenames. If
- your tarball unpacks into 'myproject-1.2.0', this should
- be 'myproject-'.
-
-To use it:
-
- 1: include this file in the top level of your project
- 2: make the following changes to the top of your setup.py:
- import versioneer
- versioneer.versionfile_source = 'src/myproject/_version.py'
- versioneer.versionfile_build = 'myproject/_version.py'
- versioneer.tag_prefix = '' # tags are like 1.2.0
- versioneer.parentdir_prefix = 'myproject-' # dirname like 'myproject-1.2.0'
- 3: add the following arguments to the setup() call in your setup.py:
- version=versioneer.get_version(),
- cmdclass=versioneer.get_cmdclass(),
- 4: run 'setup.py update_files', which will create _version.py, and will
- modify your __init__.py to define __version__ (by calling a function
- from _version.py)
- 5: modify your MANIFEST.in to include versioneer.py
- 6: add both versioneer.py and the generated _version.py to your VCS
-"""
+* Compatible With: python2.6, 2.7, 3.2, 3.3, 3.4, and pypy
+* [![Latest Version]
+(https://pypip.in/version/versioneer/badge.svg?style=flat)
+](https://pypi.python.org/pypi/versioneer/)
+* [![Build Status]
+(https://travis-ci.org/warner/python-versioneer.png?branch=master)
+](https://travis-ci.org/warner/python-versioneer)
+
+This is a tool for managing a recorded version number in distutils-based
+python projects. The goal is to remove the tedious and error-prone "update
+the embedded version string" step from your release process. Making a new
+release should be as easy as recording a new tag in your version-control
+system, and maybe making new tarballs.
+
+
+## Quick Install
+
+* `pip install versioneer` to somewhere to your $PATH
+* add a `[versioneer]` section to your setup.cfg (see below)
+* run `versioneer install` in your source tree, commit the results
+
+## Version Identifiers
+
+Source trees come from a variety of places:
+
+* a version-control system checkout (mostly used by developers)
+* a nightly tarball, produced by build automation
+* a snapshot tarball, produced by a web-based VCS browser, like github's
+ "tarball from tag" feature
+* a release tarball, produced by "setup.py sdist", distributed through PyPI
+
+Within each source tree, the version identifier (either a string or a number,
+this tool is format-agnostic) can come from a variety of places:
+
+* ask the VCS tool itself, e.g. "git describe" (for checkouts), which knows
+ about recent "tags" and an absolute revision-id
+* the name of the directory into which the tarball was unpacked
+* an expanded VCS keyword ($Id$, etc)
+* a `_version.py` created by some earlier build step
+
+For released software, the version identifier is closely related to a VCS
+tag. Some projects use tag names that include more than just the version
+string (e.g. "myproject-1.2" instead of just "1.2"), in which case the tool
+needs to strip the tag prefix to extract the version identifier. For
+unreleased software (between tags), the version identifier should provide
+enough information to help developers recreate the same tree, while also
+giving them an idea of roughly how old the tree is (after version 1.2, before
+version 1.3). Many VCS systems can report a description that captures this,
+for example `git describe --tags --dirty --always` reports things like
+"0.7-1-g574ab98-dirty" to indicate that the checkout is one revision past the
+0.7 tag, has a unique revision id of "574ab98", and is "dirty" (it has
+uncommitted changes.
+
+The version identifier is used for multiple purposes:
+
+* to allow the module to self-identify its version: `myproject.__version__`
+* to choose a name and prefix for a 'setup.py sdist' tarball
+
+## Theory of Operation
+
+Versioneer works by adding a special `_version.py` file into your source
+tree, where your `__init__.py` can import it. This `_version.py` knows how to
+dynamically ask the VCS tool for version information at import time.
+
+`_version.py` also contains `$Revision$` markers, and the installation
+process marks `_version.py` to have this marker rewritten with a tag name
+during the `git archive` command. As a result, generated tarballs will
+contain enough information to get the proper version.
+
+To allow `setup.py` to compute a version too, a `versioneer.py` is added to
+the top level of your source tree, next to `setup.py` and the `setup.cfg`
+that configures it. This overrides several distutils/setuptools commands to
+compute the version when invoked, and changes `setup.py build` and `setup.py
+sdist` to replace `_version.py` with a small static file that contains just
+the generated version data.
+
+## Installation
+
+First, decide on values for the following configuration variables:
+
+* `VCS`: the version control system you use. Currently accepts "git".
+
+* `style`: the style of version string to be produced. See "Styles" below for
+ details. Defaults to "pep440", which looks like
+ `TAG[+DISTANCE.gSHORTHASH[.dirty]]`.
+
+* `versionfile_source`:
+
+ A project-relative pathname into which the generated version strings should
+ be written. This is usually a `_version.py` next to your project's main
+ `__init__.py` file, so it can be imported at runtime. If your project uses
+ `src/myproject/__init__.py`, this should be `src/myproject/_version.py`.
+ This file should be checked in to your VCS as usual: the copy created below
+ by `setup.py setup_versioneer` will include code that parses expanded VCS
+ keywords in generated tarballs. The 'build' and 'sdist' commands will
+ replace it with a copy that has just the calculated version string.
+
+ This must be set even if your project does not have any modules (and will
+ therefore never import `_version.py`), since "setup.py sdist" -based trees
+ still need somewhere to record the pre-calculated version strings. Anywhere
+ in the source tree should do. If there is a `__init__.py` next to your
+ `_version.py`, the `setup.py setup_versioneer` command (described below)
+ will append some `__version__`-setting assignments, if they aren't already
+ present.
+
+* `versionfile_build`:
+
+ Like `versionfile_source`, but relative to the build directory instead of
+ the source directory. These will differ when your setup.py uses
+ 'package_dir='. If you have `package_dir={'myproject': 'src/myproject'}`,
+ then you will probably have `versionfile_build='myproject/_version.py'` and
+ `versionfile_source='src/myproject/_version.py'`.
+
+ If this is set to None, then `setup.py build` will not attempt to rewrite
+ any `_version.py` in the built tree. If your project does not have any
+ libraries (e.g. if it only builds a script), then you should use
+ `versionfile_build = None` and override `distutils.command.build_scripts`
+ to explicitly insert a copy of `versioneer.get_version()` into your
+ generated script.
+
+* `tag_prefix`:
+
+ a string, like 'PROJECTNAME-', which appears at the start of all VCS tags.
+ If your tags look like 'myproject-1.2.0', then you should use
+ tag_prefix='myproject-'. If you use unprefixed tags like '1.2.0', this
+ should be an empty string.
+
+* `parentdir_prefix`:
+
+ a optional string, frequently the same as tag_prefix, which appears at the
+ start of all unpacked tarball filenames. If your tarball unpacks into
+ 'myproject-1.2.0', this should be 'myproject-'. To disable this feature,
+ just omit the field from your `setup.cfg`.
+
+This tool provides one script, named `versioneer`. That script has one mode,
+"install", which writes a copy of `versioneer.py` into the current directory
+and runs `versioneer.py setup` to finish the installation.
+
+To versioneer-enable your project:
+
+* 1: Modify your `setup.cfg`, adding a section named `[versioneer]` and
+ populating it with the configuration values you decided earlier (note that
+ the option names are not case-sensitive):
+
+ ````
+ [versioneer]
+ VCS = git
+ style = pep440
+ versionfile_source = src/myproject/_version.py
+ versionfile_build = myproject/_version.py
+ tag_prefix = ""
+ parentdir_prefix = myproject-
+ ````
+
+* 2: Run `versioneer install`. This will do the following:
+
+ * copy `versioneer.py` into the top of your source tree
+ * create `_version.py` in the right place (`versionfile_source`)
+ * modify your `__init__.py` (if one exists next to `_version.py`) to define
+ `__version__` (by calling a function from `_version.py`)
+ * modify your `MANIFEST.in` to include both `versioneer.py` and the
+ generated `_version.py` in sdist tarballs
+
+ `versioneer install` will complain about any problems it finds with your
+ `setup.py` or `setup.cfg`. Run it multiple times until you have fixed all
+ the problems.
+
+* 3: add a `import versioneer` to your setup.py, and add the following
+ arguments to the setup() call:
+
+ version=versioneer.get_version(),
+ cmdclass=versioneer.get_cmdclass(),
+
+* 4: commit these changes to your VCS. To make sure you won't forget,
+ `versioneer install` will mark everything it touched for addition using
+ `git add`. Don't forget to add `setup.py` and `setup.cfg` too.
+
+## Post-Installation Usage
+
+Once established, all uses of your tree from a VCS checkout should get the
+current version string. All generated tarballs should include an embedded
+version string (so users who unpack them will not need a VCS tool installed).
+
+If you distribute your project through PyPI, then the release process should
+boil down to two steps:
+
+* 1: git tag 1.0
+* 2: python setup.py register sdist upload
+
+If you distribute it through github (i.e. users use github to generate
+tarballs with `git archive`), the process is:
+
+* 1: git tag 1.0
+* 2: git push; git push --tags
+
+Versioneer will report "0+untagged.NUMCOMMITS.gHASH" until your tree has at
+least one tag in its history.
+
+## Version-String Flavors
+
+Code which uses Versioneer can learn about its version string at runtime by
+importing `_version` from your main `__init__.py` file and running the
+`get_versions()` function. From the "outside" (e.g. in `setup.py`), you can
+import the top-level `versioneer.py` and run `get_versions()`.
+
+Both functions return a dictionary with different flavors of version
+information:
+
+* `['version']`: A condensed version string, rendered using the selected
+ style. This is the most commonly used value for the project's version
+ string. The default "pep440" style yields strings like `0.11`,
+ `0.11+2.g1076c97`, or `0.11+2.g1076c97.dirty`. See the "Styles" section
+ below for alternative styles.
+
+* `['full-revisionid']`: detailed revision identifier. For Git, this is the
+ full SHA1 commit id, e.g. "1076c978a8d3cfc70f408fe5974aa6c092c949ac".
+
+* `['dirty']`: a boolean, True if the tree has uncommitted changes. Note that
+ this is only accurate if run in a VCS checkout, otherwise it is likely to
+ be False or None
+
+* `['error']`: if the version string could not be computed, this will be set
+ to a string describing the problem, otherwise it will be None. It may be
+ useful to throw an exception in setup.py if this is set, to avoid e.g.
+ creating tarballs with a version string of "unknown".
+
+Some variants are more useful than others. Including `full-revisionid` in a
+bug report should allow developers to reconstruct the exact code being tested
+(or indicate the presence of local changes that should be shared with the
+developers). `version` is suitable for display in an "about" box or a CLI
+`--version` output: it can be easily compared against release notes and lists
+of bugs fixed in various releases.
+
+The installer adds the following text to your `__init__.py` to place a basic
+version in `YOURPROJECT.__version__`:
+
+ from ._version import get_versions
+ __version__ = get_versions()['version']
+ del get_versions
+
+## Styles
+
+The setup.cfg `style=` configuration controls how the VCS information is
+rendered into a version string.
+
+The default style, "pep440", produces a PEP440-compliant string, equal to the
+un-prefixed tag name for actual releases, and containing an additional "local
+version" section with more detail for in-between builds. For Git, this is
+TAG[+DISTANCE.gHEX[.dirty]] , using information from `git describe --tags
+--dirty --always`. For example "0.11+2.g1076c97.dirty" indicates that the
+tree is like the "1076c97" commit but has uncommitted changes (".dirty"), and
+that this commit is two revisions ("+2") beyond the "0.11" tag. For released
+software (exactly equal to a known tag), the identifier will only contain the
+stripped tag, e.g. "0.11".
+
+Other styles are available. See details.md in the Versioneer source tree for
+descriptions.
+
+## Debugging
+
+Versioneer tries to avoid fatal errors: if something goes wrong, it will tend
+to return a version of "0+unknown". To investigate the problem, run `setup.py
+version`, which will run the version-lookup code in a verbose mode, and will
+display the full contents of `get_versions()` (including the `error` string,
+which may help identify what went wrong).
+
+## Updating Versioneer
+
+To upgrade your project to a new release of Versioneer, do the following:
+
+* install the new Versioneer (`pip install -U versioneer` or equivalent)
+* edit `setup.cfg`, if necessary, to include any new configuration settings
+ indicated by the release notes
+* re-run `versioneer install` in your source tree, to replace
+ `SRC/_version.py`
+* commit any changed files
+
+### Upgrading to 0.15
+
+Starting with this version, Versioneer is configured with a `[versioneer]`
+section in your `setup.cfg` file. Earlier versions required the `setup.py` to
+set attributes on the `versioneer` module immediately after import. The new
+version will refuse to run (raising an exception during import) until you
+have provided the necessary `setup.cfg` section.
+
+In addition, the Versioneer package provides an executable named
+`versioneer`, and the installation process is driven by running `versioneer
+install`. In 0.14 and earlier, the executable was named
+`versioneer-installer` and was run without an argument.
+
+### Upgrading to 0.14
+
+0.14 changes the format of the version string. 0.13 and earlier used
+hyphen-separated strings like "0.11-2-g1076c97-dirty". 0.14 and beyond use a
+plus-separated "local version" section strings, with dot-separated
+components, like "0.11+2.g1076c97". PEP440-strict tools did not like the old
+format, but should be ok with the new one.
+
+### Upgrading from 0.11 to 0.12
+
+Nothing special.
+
+### Upgrading from 0.10 to 0.11
-import os, sys, re
-from distutils.core import Command
-from distutils.command.sdist import sdist as _sdist
-from distutils.command.build import build as _build
+You must add a `versioneer.VCS = "git"` to your `setup.py` before re-running
+`setup.py setup_versioneer`. This will enable the use of additional
+version-control systems (SVN, etc) in the future.
-versionfile_source = None
-versionfile_build = None
-tag_prefix = None
-parentdir_prefix = None
+## Future Directions
-VCS = "git"
-IN_LONG_VERSION_PY = False
+This tool is designed to make it easily extended to other version-control
+systems: all VCS-specific components are in separate directories like
+src/git/ . The top-level `versioneer.py` script is assembled from these
+components by running make-versioneer.py . In the future, make-versioneer.py
+will take a VCS name as an argument, and will construct a version of
+`versioneer.py` that is specific to the given VCS. It might also take the
+configuration arguments that are currently provided manually during
+installation by editing setup.py . Alternatively, it might go the other
+direction and include code from all supported VCS systems, reducing the
+number of intermediate scripts.
-LONG_VERSION_PY = '''
-IN_LONG_VERSION_PY = True
+## License
+
+To make Versioneer easier to embed, all its code is hereby released into the
+public domain. The `_version.py` that it creates is also in the public
+domain.
+
+"""
+
+from __future__ import print_function
+try:
+ import configparser
+except ImportError:
+ import ConfigParser as configparser
+import errno
+import json
+import os
+import re
+import subprocess
+import sys
+
+
+class VersioneerConfig:
+ pass
+
+
+def get_root():
+ # we require that all commands are run from the project root, i.e. the
+ # directory that contains setup.py, setup.cfg, and versioneer.py .
+ root = os.path.realpath(os.path.abspath(os.getcwd()))
+ setup_py = os.path.join(root, "setup.py")
+ versioneer_py = os.path.join(root, "versioneer.py")
+ if not (os.path.exists(setup_py) or os.path.exists(versioneer_py)):
+ # allow 'python path/to/setup.py COMMAND'
+ root = os.path.dirname(os.path.realpath(os.path.abspath(sys.argv[0])))
+ setup_py = os.path.join(root, "setup.py")
+ versioneer_py = os.path.join(root, "versioneer.py")
+ if not (os.path.exists(setup_py) or os.path.exists(versioneer_py)):
+ err = ("Versioneer was unable to run the project root directory. "
+ "Versioneer requires setup.py to be executed from "
+ "its immediate directory (like 'python setup.py COMMAND'), "
+ "or in a way that lets it use sys.argv[0] to find the root "
+ "(like 'python path/to/setup.py COMMAND').")
+ raise VersioneerBadRootError(err)
+ try:
+ # Certain runtime workflows (setup.py install/develop in a setuptools
+ # tree) execute all dependencies in a single python process, so
+ # "versioneer" may be imported multiple times, and python's shared
+ # module-import table will cache the first one. So we can't use
+ # os.path.dirname(__file__), as that will find whichever
+ # versioneer.py was first imported, even in later projects.
+ me = os.path.realpath(os.path.abspath(__file__))
+ if os.path.splitext(me)[0] != os.path.splitext(versioneer_py)[0]:
+ print("Warning: build in %s is using versioneer.py from %s"
+ % (os.path.dirname(me), versioneer_py))
+ except NameError:
+ pass
+ return root
+
+
+def get_config_from_root(root):
+ # This might raise EnvironmentError (if setup.cfg is missing), or
+ # configparser.NoSectionError (if it lacks a [versioneer] section), or
+ # configparser.NoOptionError (if it lacks "VCS="). See the docstring at
+ # the top of versioneer.py for instructions on writing your setup.cfg .
+ setup_cfg = os.path.join(root, "setup.cfg")
+ parser = configparser.SafeConfigParser()
+ with open(setup_cfg, "r") as f:
+ parser.readfp(f)
+ VCS = parser.get("versioneer", "VCS") # mandatory
+
+ def get(parser, name):
+ if parser.has_option("versioneer", name):
+ return parser.get("versioneer", name)
+ return None
+ cfg = VersioneerConfig()
+ cfg.VCS = VCS
+ cfg.style = get(parser, "style") or ""
+ cfg.versionfile_source = get(parser, "versionfile_source")
+ cfg.versionfile_build = get(parser, "versionfile_build")
+ cfg.tag_prefix = get(parser, "tag_prefix")
+ cfg.parentdir_prefix = get(parser, "parentdir_prefix")
+ cfg.verbose = get(parser, "verbose")
+ return cfg
+
+
+class NotThisMethod(Exception):
+ pass
+
+# these dictionaries contain VCS-specific tools
+LONG_VERSION_PY = {}
+HANDLERS = {}
+
+
+def register_vcs_handler(vcs, method): # decorator
+ def decorate(f):
+ if vcs not in HANDLERS:
+ HANDLERS[vcs] = {}
+ HANDLERS[vcs][method] = f
+ return f
+ return decorate
+
+
+def run_command(commands, args, cwd=None, verbose=False, hide_stderr=False):
+ assert isinstance(commands, list)
+ p = None
+ for c in commands:
+ try:
+ dispcmd = str([c] + args)
+ # remember shell=False, so use git.cmd on windows, not just git
+ p = subprocess.Popen([c] + args, cwd=cwd, stdout=subprocess.PIPE,
+ stderr=(subprocess.PIPE if hide_stderr
+ else None))
+ break
+ except EnvironmentError:
+ e = sys.exc_info()[1]
+ if e.errno == errno.ENOENT:
+ continue
+ if verbose:
+ print("unable to run %s" % dispcmd)
+ print(e)
+ return None
+ else:
+ if verbose:
+ print("unable to find command, tried %s" % (commands,))
+ return None
+ stdout = p.communicate()[0].strip()
+ if sys.version_info[0] >= 3:
+ stdout = stdout.decode()
+ if p.returncode != 0:
+ if verbose:
+ print("unable to run %s (error)" % dispcmd)
+ return None
+ return stdout
+LONG_VERSION_PY['git'] = '''
# This file helps to compute a version number in source trees obtained from
# git-archive tarball (such as those provided by githubs download-from-tag
-# feature). Distribution tarballs (build by setup.py sdist) and build
+# feature). Distribution tarballs (built by setup.py sdist) and build
# directories (produced by setup.py build) will contain a much shorter file
# that just contains the computed version number.
# This file is released into the public domain. Generated by
-# versioneer-0.7+ (https://github.com/warner/python-versioneer)
-
-# these strings will be replaced by git during git-archive
-git_refnames = "%(DOLLAR)sFormat:%%d%(DOLLAR)s"
-git_full = "%(DOLLAR)sFormat:%%H%(DOLLAR)s"
-
+# versioneer-0.15 (https://github.com/warner/python-versioneer)
+import errno
+import os
+import re
import subprocess
import sys
-def run_command(args, cwd=None, verbose=False):
- try:
- # remember shell=False, so use git.cmd on windows, not just git
- p = subprocess.Popen(args, stdout=subprocess.PIPE, cwd=cwd)
- except EnvironmentError:
- e = sys.exc_info()[1]
+
+def get_keywords():
+ # these strings will be replaced by git during git-archive.
+ # setup.py/versioneer.py will grep for the variable names, so they must
+ # each be defined on a line of their own. _version.py will just call
+ # get_keywords().
+ git_refnames = "%(DOLLAR)sFormat:%%d%(DOLLAR)s"
+ git_full = "%(DOLLAR)sFormat:%%H%(DOLLAR)s"
+ keywords = {"refnames": git_refnames, "full": git_full}
+ return keywords
+
+
+class VersioneerConfig:
+ pass
+
+
+def get_config():
+ # these strings are filled in when 'setup.py versioneer' creates
+ # _version.py
+ cfg = VersioneerConfig()
+ cfg.VCS = "git"
+ cfg.style = "%(STYLE)s"
+ cfg.tag_prefix = "%(TAG_PREFIX)s"
+ cfg.parentdir_prefix = "%(PARENTDIR_PREFIX)s"
+ cfg.versionfile_source = "%(VERSIONFILE_SOURCE)s"
+ cfg.verbose = False
+ return cfg
+
+
+class NotThisMethod(Exception):
+ pass
+
+
+LONG_VERSION_PY = {}
+HANDLERS = {}
+
+
+def register_vcs_handler(vcs, method): # decorator
+ def decorate(f):
+ if vcs not in HANDLERS:
+ HANDLERS[vcs] = {}
+ HANDLERS[vcs][method] = f
+ return f
+ return decorate
+
+
+def run_command(commands, args, cwd=None, verbose=False, hide_stderr=False):
+ assert isinstance(commands, list)
+ p = None
+ for c in commands:
+ try:
+ dispcmd = str([c] + args)
+ # remember shell=False, so use git.cmd on windows, not just git
+ p = subprocess.Popen([c] + args, cwd=cwd, stdout=subprocess.PIPE,
+ stderr=(subprocess.PIPE if hide_stderr
+ else None))
+ break
+ except EnvironmentError:
+ e = sys.exc_info()[1]
+ if e.errno == errno.ENOENT:
+ continue
+ if verbose:
+ print("unable to run %%s" %% dispcmd)
+ print(e)
+ return None
+ else:
if verbose:
- print("unable to run %%s" %% args[0])
- print(e)
+ print("unable to find command, tried %%s" %% (commands,))
return None
stdout = p.communicate()[0].strip()
- if sys.version >= '3':
+ if sys.version_info[0] >= 3:
stdout = stdout.decode()
if p.returncode != 0:
if verbose:
- print("unable to run %%s (error)" %% args[0])
+ print("unable to run %%s (error)" %% dispcmd)
return None
return stdout
-import sys
-import re
-import os.path
+def versions_from_parentdir(parentdir_prefix, root, verbose):
+ # Source tarballs conventionally unpack into a directory that includes
+ # both the project name and a version string.
+ dirname = os.path.basename(root)
+ if not dirname.startswith(parentdir_prefix):
+ if verbose:
+ print("guessing rootdir is '%%s', but '%%s' doesn't start with "
+ "prefix '%%s'" %% (root, dirname, parentdir_prefix))
+ raise NotThisMethod("rootdir doesn't start with parentdir_prefix")
+ return {"version": dirname[len(parentdir_prefix):],
+ "full-revisionid": None,
+ "dirty": False, "error": None}
+
-def get_expanded_variables(versionfile_source):
+@register_vcs_handler("git", "get_keywords")
+def git_get_keywords(versionfile_abs):
# the code embedded in _version.py can just fetch the value of these
- # variables. When used from setup.py, we don't want to import
- # _version.py, so we do it with a regexp instead. This function is not
- # used from _version.py.
- variables = {}
+ # keywords. When used from setup.py, we don't want to import _version.py,
+ # so we do it with a regexp instead. This function is not used from
+ # _version.py.
+ keywords = {}
try:
- f = open(versionfile_source,"r")
+ f = open(versionfile_abs, "r")
for line in f.readlines():
if line.strip().startswith("git_refnames ="):
mo = re.search(r'=\s*"(.*)"', line)
if mo:
- variables["refnames"] = mo.group(1)
+ keywords["refnames"] = mo.group(1)
if line.strip().startswith("git_full ="):
mo = re.search(r'=\s*"(.*)"', line)
if mo:
- variables["full"] = mo.group(1)
+ keywords["full"] = mo.group(1)
f.close()
except EnvironmentError:
pass
- return variables
+ return keywords
+
-def versions_from_expanded_variables(variables, tag_prefix, verbose=False):
- refnames = variables["refnames"].strip()
+@register_vcs_handler("git", "keywords")
+def git_versions_from_keywords(keywords, tag_prefix, verbose):
+ if not keywords:
+ raise NotThisMethod("no keywords at all, weird")
+ refnames = keywords["refnames"].strip()
if refnames.startswith("$Format"):
if verbose:
- print("variables are unexpanded, not using")
- return {} # unexpanded, so not in an unpacked git-archive tarball
+ print("keywords are unexpanded, not using")
+ raise NotThisMethod("unexpanded keywords, not a git-archive tarball")
refs = set([r.strip() for r in refnames.strip("()").split(",")])
# starting in git-1.8.3, tags are listed as "tag: foo-1.0" instead of
# just "foo-1.0". If we see a "tag: " prefix, prefer those.
@@ -189,172 +630,336 @@ def versions_from_expanded_variables(variables, tag_prefix, verbose=False):
r = ref[len(tag_prefix):]
if verbose:
print("picking %%s" %% r)
- return { "version": r,
- "full": variables["full"].strip() }
- # no suitable tags, so we use the full revision id
+ return {"version": r,
+ "full-revisionid": keywords["full"].strip(),
+ "dirty": False, "error": None
+ }
+ # no suitable tags, so version is "0+unknown", but full hex is still there
if verbose:
- print("no suitable tags, using full revision id")
- return { "version": variables["full"].strip(),
- "full": variables["full"].strip() }
-
-def versions_from_vcs(tag_prefix, versionfile_source, verbose=False):
- # this runs 'git' from the root of the source tree. That either means
- # someone ran a setup.py command (and this code is in versioneer.py, so
- # IN_LONG_VERSION_PY=False, thus the containing directory is the root of
- # the source tree), or someone ran a project-specific entry point (and
- # this code is in _version.py, so IN_LONG_VERSION_PY=True, thus the
- # containing directory is somewhere deeper in the source tree). This only
- # gets called if the git-archive 'subst' variables were *not* expanded,
- # and _version.py hasn't already been rewritten with a short version
- # string, meaning we're inside a checked out source tree.
+ print("no suitable tags, using unknown + full revision id")
+ return {"version": "0+unknown",
+ "full-revisionid": keywords["full"].strip(),
+ "dirty": False, "error": "no suitable tags"}
+
+
+@register_vcs_handler("git", "pieces_from_vcs")
+def git_pieces_from_vcs(tag_prefix, root, verbose, run_command=run_command):
+ # this runs 'git' from the root of the source tree. This only gets called
+ # if the git-archive 'subst' keywords were *not* expanded, and
+ # _version.py hasn't already been rewritten with a short version string,
+ # meaning we're inside a checked out source tree.
- try:
- here = os.path.abspath(__file__)
- except NameError:
- # some py2exe/bbfreeze/non-CPython implementations don't do __file__
- return {} # not always correct
-
- # versionfile_source is the relative path from the top of the source tree
- # (where the .git directory might live) to this file. Invert this to find
- # the root from __file__.
- root = here
- if IN_LONG_VERSION_PY:
- for i in range(len(versionfile_source.split("/"))):
- root = os.path.dirname(root)
- else:
- root = os.path.dirname(here)
if not os.path.exists(os.path.join(root, ".git")):
if verbose:
print("no .git in %%s" %% root)
- return {}
+ raise NotThisMethod("no .git directory")
- GIT = "git"
+ GITS = ["git"]
if sys.platform == "win32":
- GIT = "git.exe"
- stdout = run_command([GIT, "describe", "--tags", "--dirty", "--always"],
- cwd=root)
- if stdout is None:
- return {}
- if not stdout.startswith(tag_prefix):
- if verbose:
- print("tag '%%s' doesn't start with prefix '%%s'" %% (stdout, tag_prefix))
- return {}
- tag = stdout[len(tag_prefix):]
- stdout = run_command([GIT, "rev-parse", "HEAD"], cwd=root)
- if stdout is None:
- return {}
- full = stdout.strip()
- if tag.endswith("-dirty"):
- full += "-dirty"
- return {"version": tag, "full": full}
-
-
-def versions_from_parentdir(parentdir_prefix, versionfile_source, verbose=False):
- if IN_LONG_VERSION_PY:
- # We're running from _version.py. If it's from a source tree
- # (execute-in-place), we can work upwards to find the root of the
- # tree, and then check the parent directory for a version string. If
- # it's in an installed application, there's no hope.
- try:
- here = os.path.abspath(__file__)
- except NameError:
- # py2exe/bbfreeze/non-CPython don't have __file__
- return {} # without __file__, we have no hope
- # versionfile_source is the relative path from the top of the source
- # tree to _version.py. Invert this to find the root from __file__.
- root = here
- for i in range(len(versionfile_source.split("/"))):
- root = os.path.dirname(root)
+ GITS = ["git.cmd", "git.exe"]
+ # if there is a tag, this yields TAG-NUM-gHEX[-dirty]
+ # if there are no tags, this yields HEX[-dirty] (no NUM)
+ describe_out = run_command(GITS, ["describe", "--tags", "--dirty",
+ "--always", "--long"],
+ cwd=root)
+ # --long was added in git-1.5.5
+ if describe_out is None:
+ raise NotThisMethod("'git describe' failed")
+ describe_out = describe_out.strip()
+ full_out = run_command(GITS, ["rev-parse", "HEAD"], cwd=root)
+ if full_out is None:
+ raise NotThisMethod("'git rev-parse' failed")
+ full_out = full_out.strip()
+
+ pieces = {}
+ pieces["long"] = full_out
+ pieces["short"] = full_out[:7] # maybe improved later
+ pieces["error"] = None
+
+ # parse describe_out. It will be like TAG-NUM-gHEX[-dirty] or HEX[-dirty]
+ # TAG might have hyphens.
+ git_describe = describe_out
+
+ # look for -dirty suffix
+ dirty = git_describe.endswith("-dirty")
+ pieces["dirty"] = dirty
+ if dirty:
+ git_describe = git_describe[:git_describe.rindex("-dirty")]
+
+ # now we have TAG-NUM-gHEX or HEX
+
+ if "-" in git_describe:
+ # TAG-NUM-gHEX
+ mo = re.search(r'^(.+)-(\d+)-g([0-9a-f]+)$', git_describe)
+ if not mo:
+ # unparseable. Maybe git-describe is misbehaving?
+ pieces["error"] = ("unable to parse git-describe output: '%%s'"
+ %% describe_out)
+ return pieces
+
+ # tag
+ full_tag = mo.group(1)
+ if not full_tag.startswith(tag_prefix):
+ if verbose:
+ fmt = "tag '%%s' doesn't start with prefix '%%s'"
+ print(fmt %% (full_tag, tag_prefix))
+ pieces["error"] = ("tag '%%s' doesn't start with prefix '%%s'"
+ %% (full_tag, tag_prefix))
+ return pieces
+ pieces["closest-tag"] = full_tag[len(tag_prefix):]
+
+ # distance: number of commits since tag
+ pieces["distance"] = int(mo.group(2))
+
+ # commit: short hex revision ID
+ pieces["short"] = mo.group(3)
+
else:
- # we're running from versioneer.py, which means we're running from
- # the setup.py in a source tree. sys.argv[0] is setup.py in the root.
- here = os.path.abspath(sys.argv[0])
- root = os.path.dirname(here)
+ # HEX: no tags
+ pieces["closest-tag"] = None
+ count_out = run_command(GITS, ["rev-list", "HEAD", "--count"],
+ cwd=root)
+ pieces["distance"] = int(count_out) # total number of commits
- # Source tarballs conventionally unpack into a directory that includes
- # both the project name and a version string.
- dirname = os.path.basename(root)
- if not dirname.startswith(parentdir_prefix):
- if verbose:
- print("guessing rootdir is '%%s', but '%%s' doesn't start with prefix '%%s'" %%
- (root, dirname, parentdir_prefix))
- return None
- return {"version": dirname[len(parentdir_prefix):], "full": ""}
-
-tag_prefix = "%(TAG_PREFIX)s"
-parentdir_prefix = "%(PARENTDIR_PREFIX)s"
-versionfile_source = "%(VERSIONFILE_SOURCE)s"
-
-def get_versions(default={"version": "unknown", "full": ""}, verbose=False):
- variables = { "refnames": git_refnames, "full": git_full }
- ver = versions_from_expanded_variables(variables, tag_prefix, verbose)
- if not ver:
- ver = versions_from_vcs(tag_prefix, versionfile_source, verbose)
- if not ver:
- ver = versions_from_parentdir(parentdir_prefix, versionfile_source,
- verbose)
- if not ver:
- ver = default
- return ver
+ return pieces
-'''
+def plus_or_dot(pieces):
+ if "+" in pieces.get("closest-tag", ""):
+ return "."
+ return "+"
-import subprocess
-import sys
-def run_command(args, cwd=None, verbose=False):
+def render_pep440(pieces):
+ # now build up version string, with post-release "local version
+ # identifier". Our goal: TAG[+DISTANCE.gHEX[.dirty]] . Note that if you
+ # get a tagged build and then dirty it, you'll get TAG+0.gHEX.dirty
+
+ # exceptions:
+ # 1: no tags. git_describe was just HEX. 0+untagged.DISTANCE.gHEX[.dirty]
+
+ if pieces["closest-tag"]:
+ rendered = pieces["closest-tag"]
+ if pieces["distance"] or pieces["dirty"]:
+ rendered += plus_or_dot(pieces)
+ rendered += "%%d.g%%s" %% (pieces["distance"], pieces["short"])
+ if pieces["dirty"]:
+ rendered += ".dirty"
+ else:
+ # exception #1
+ rendered = "0+untagged.%%d.g%%s" %% (pieces["distance"],
+ pieces["short"])
+ if pieces["dirty"]:
+ rendered += ".dirty"
+ return rendered
+
+
+def render_pep440_pre(pieces):
+ # TAG[.post.devDISTANCE] . No -dirty
+
+ # exceptions:
+ # 1: no tags. 0.post.devDISTANCE
+
+ if pieces["closest-tag"]:
+ rendered = pieces["closest-tag"]
+ if pieces["distance"]:
+ rendered += ".post.dev%%d" %% pieces["distance"]
+ else:
+ # exception #1
+ rendered = "0.post.dev%%d" %% pieces["distance"]
+ return rendered
+
+
+def render_pep440_post(pieces):
+ # TAG[.postDISTANCE[.dev0]+gHEX] . The ".dev0" means dirty. Note that
+ # .dev0 sorts backwards (a dirty tree will appear "older" than the
+ # corresponding clean one), but you shouldn't be releasing software with
+ # -dirty anyways.
+
+ # exceptions:
+ # 1: no tags. 0.postDISTANCE[.dev0]
+
+ if pieces["closest-tag"]:
+ rendered = pieces["closest-tag"]
+ if pieces["distance"] or pieces["dirty"]:
+ rendered += ".post%%d" %% pieces["distance"]
+ if pieces["dirty"]:
+ rendered += ".dev0"
+ rendered += plus_or_dot(pieces)
+ rendered += "g%%s" %% pieces["short"]
+ else:
+ # exception #1
+ rendered = "0.post%%d" %% pieces["distance"]
+ if pieces["dirty"]:
+ rendered += ".dev0"
+ rendered += "+g%%s" %% pieces["short"]
+ return rendered
+
+
+def render_pep440_old(pieces):
+ # TAG[.postDISTANCE[.dev0]] . The ".dev0" means dirty.
+
+ # exceptions:
+ # 1: no tags. 0.postDISTANCE[.dev0]
+
+ if pieces["closest-tag"]:
+ rendered = pieces["closest-tag"]
+ if pieces["distance"] or pieces["dirty"]:
+ rendered += ".post%%d" %% pieces["distance"]
+ if pieces["dirty"]:
+ rendered += ".dev0"
+ else:
+ # exception #1
+ rendered = "0.post%%d" %% pieces["distance"]
+ if pieces["dirty"]:
+ rendered += ".dev0"
+ return rendered
+
+
+def render_git_describe(pieces):
+ # TAG[-DISTANCE-gHEX][-dirty], like 'git describe --tags --dirty
+ # --always'
+
+ # exceptions:
+ # 1: no tags. HEX[-dirty] (note: no 'g' prefix)
+
+ if pieces["closest-tag"]:
+ rendered = pieces["closest-tag"]
+ if pieces["distance"]:
+ rendered += "-%%d-g%%s" %% (pieces["distance"], pieces["short"])
+ else:
+ # exception #1
+ rendered = pieces["short"]
+ if pieces["dirty"]:
+ rendered += "-dirty"
+ return rendered
+
+
+def render_git_describe_long(pieces):
+ # TAG-DISTANCE-gHEX[-dirty], like 'git describe --tags --dirty
+ # --always -long'. The distance/hash is unconditional.
+
+ # exceptions:
+ # 1: no tags. HEX[-dirty] (note: no 'g' prefix)
+
+ if pieces["closest-tag"]:
+ rendered = pieces["closest-tag"]
+ rendered += "-%%d-g%%s" %% (pieces["distance"], pieces["short"])
+ else:
+ # exception #1
+ rendered = pieces["short"]
+ if pieces["dirty"]:
+ rendered += "-dirty"
+ return rendered
+
+
+def render(pieces, style):
+ if pieces["error"]:
+ return {"version": "unknown",
+ "full-revisionid": pieces.get("long"),
+ "dirty": None,
+ "error": pieces["error"]}
+
+ if not style or style == "default":
+ style = "pep440" # the default
+
+ if style == "pep440":
+ rendered = render_pep440(pieces)
+ elif style == "pep440-pre":
+ rendered = render_pep440_pre(pieces)
+ elif style == "pep440-post":
+ rendered = render_pep440_post(pieces)
+ elif style == "pep440-old":
+ rendered = render_pep440_old(pieces)
+ elif style == "git-describe":
+ rendered = render_git_describe(pieces)
+ elif style == "git-describe-long":
+ rendered = render_git_describe_long(pieces)
+ else:
+ raise ValueError("unknown style '%%s'" %% style)
+
+ return {"version": rendered, "full-revisionid": pieces["long"],
+ "dirty": pieces["dirty"], "error": None}
+
+
+def get_versions():
+ # I am in _version.py, which lives at ROOT/VERSIONFILE_SOURCE. If we have
+ # __file__, we can work backwards from there to the root. Some
+ # py2exe/bbfreeze/non-CPython implementations don't do __file__, in which
+ # case we can only use expanded keywords.
+
+ cfg = get_config()
+ verbose = cfg.verbose
+
try:
- # remember shell=False, so use git.cmd on windows, not just git
- p = subprocess.Popen(args, stdout=subprocess.PIPE, cwd=cwd)
- except EnvironmentError:
- e = sys.exc_info()[1]
- if verbose:
- print("unable to run %s" % args[0])
- print(e)
- return None
- stdout = p.communicate()[0].strip()
- if sys.version >= '3':
- stdout = stdout.decode()
- if p.returncode != 0:
- if verbose:
- print("unable to run %s (error)" % args[0])
- return None
- return stdout
+ return git_versions_from_keywords(get_keywords(), cfg.tag_prefix,
+ verbose)
+ except NotThisMethod:
+ pass
+ try:
+ root = os.path.realpath(__file__)
+ # versionfile_source is the relative path from the top of the source
+ # tree (where the .git directory might live) to this file. Invert
+ # this to find the root from __file__.
+ for i in cfg.versionfile_source.split('/'):
+ root = os.path.dirname(root)
+ except NameError:
+ return {"version": "0+unknown", "full-revisionid": None,
+ "dirty": None,
+ "error": "unable to find root of source tree"}
-import sys
-import re
-import os.path
+ try:
+ pieces = git_pieces_from_vcs(cfg.tag_prefix, root, verbose)
+ return render(pieces, cfg.style)
+ except NotThisMethod:
+ pass
-def get_expanded_variables(versionfile_source):
+ try:
+ if cfg.parentdir_prefix:
+ return versions_from_parentdir(cfg.parentdir_prefix, root, verbose)
+ except NotThisMethod:
+ pass
+
+ return {"version": "0+unknown", "full-revisionid": None,
+ "dirty": None,
+ "error": "unable to compute version"}
+'''
+
+
+@register_vcs_handler("git", "get_keywords")
+def git_get_keywords(versionfile_abs):
# the code embedded in _version.py can just fetch the value of these
- # variables. When used from setup.py, we don't want to import
- # _version.py, so we do it with a regexp instead. This function is not
- # used from _version.py.
- variables = {}
+ # keywords. When used from setup.py, we don't want to import _version.py,
+ # so we do it with a regexp instead. This function is not used from
+ # _version.py.
+ keywords = {}
try:
- f = open(versionfile_source,"r")
+ f = open(versionfile_abs, "r")
for line in f.readlines():
if line.strip().startswith("git_refnames ="):
mo = re.search(r'=\s*"(.*)"', line)
if mo:
- variables["refnames"] = mo.group(1)
+ keywords["refnames"] = mo.group(1)
if line.strip().startswith("git_full ="):
mo = re.search(r'=\s*"(.*)"', line)
if mo:
- variables["full"] = mo.group(1)
+ keywords["full"] = mo.group(1)
f.close()
except EnvironmentError:
pass
- return variables
+ return keywords
+
-def versions_from_expanded_variables(variables, tag_prefix, verbose=False):
- refnames = variables["refnames"].strip()
+@register_vcs_handler("git", "keywords")
+def git_versions_from_keywords(keywords, tag_prefix, verbose):
+ if not keywords:
+ raise NotThisMethod("no keywords at all, weird")
+ refnames = keywords["refnames"].strip()
if refnames.startswith("$Format"):
if verbose:
- print("variables are unexpanded, not using")
- return {} # unexpanded, so not in an unpacked git-archive tarball
+ print("keywords are unexpanded, not using")
+ raise NotThisMethod("unexpanded keywords, not a git-archive tarball")
refs = set([r.strip() for r in refnames.strip("()").split(",")])
# starting in git-1.8.3, tags are listed as "tag: foo-1.0" instead of
# just "foo-1.0". If we see a "tag: " prefix, prefer those.
@@ -379,107 +984,115 @@ def versions_from_expanded_variables(variables, tag_prefix, verbose=False):
r = ref[len(tag_prefix):]
if verbose:
print("picking %s" % r)
- return { "version": r,
- "full": variables["full"].strip() }
- # no suitable tags, so we use the full revision id
+ return {"version": r,
+ "full-revisionid": keywords["full"].strip(),
+ "dirty": False, "error": None
+ }
+ # no suitable tags, so version is "0+unknown", but full hex is still there
if verbose:
- print("no suitable tags, using full revision id")
- return { "version": variables["full"].strip(),
- "full": variables["full"].strip() }
-
-def versions_from_vcs(tag_prefix, versionfile_source, verbose=False):
- # this runs 'git' from the root of the source tree. That either means
- # someone ran a setup.py command (and this code is in versioneer.py, so
- # IN_LONG_VERSION_PY=False, thus the containing directory is the root of
- # the source tree), or someone ran a project-specific entry point (and
- # this code is in _version.py, so IN_LONG_VERSION_PY=True, thus the
- # containing directory is somewhere deeper in the source tree). This only
- # gets called if the git-archive 'subst' variables were *not* expanded,
- # and _version.py hasn't already been rewritten with a short version
- # string, meaning we're inside a checked out source tree.
+ print("no suitable tags, using unknown + full revision id")
+ return {"version": "0+unknown",
+ "full-revisionid": keywords["full"].strip(),
+ "dirty": False, "error": "no suitable tags"}
+
+
+@register_vcs_handler("git", "pieces_from_vcs")
+def git_pieces_from_vcs(tag_prefix, root, verbose, run_command=run_command):
+ # this runs 'git' from the root of the source tree. This only gets called
+ # if the git-archive 'subst' keywords were *not* expanded, and
+ # _version.py hasn't already been rewritten with a short version string,
+ # meaning we're inside a checked out source tree.
- try:
- here = os.path.abspath(__file__)
- except NameError:
- # some py2exe/bbfreeze/non-CPython implementations don't do __file__
- return {} # not always correct
-
- # versionfile_source is the relative path from the top of the source tree
- # (where the .git directory might live) to this file. Invert this to find
- # the root from __file__.
- root = here
- if IN_LONG_VERSION_PY:
- for i in range(len(versionfile_source.split("/"))):
- root = os.path.dirname(root)
- else:
- root = os.path.dirname(here)
if not os.path.exists(os.path.join(root, ".git")):
if verbose:
print("no .git in %s" % root)
- return {}
+ raise NotThisMethod("no .git directory")
- GIT = "git"
+ GITS = ["git"]
if sys.platform == "win32":
- GIT = "git.exe"
- stdout = run_command([GIT, "describe", "--tags", "--dirty", "--always"],
- cwd=root)
- if stdout is None:
- return {}
- if not stdout.startswith(tag_prefix):
- if verbose:
- print("tag '%s' doesn't start with prefix '%s'" % (stdout, tag_prefix))
- return {}
- tag = stdout[len(tag_prefix):]
- stdout = run_command([GIT, "rev-parse", "HEAD"], cwd=root)
- if stdout is None:
- return {}
- full = stdout.strip()
- if tag.endswith("-dirty"):
- full += "-dirty"
- return {"version": tag, "full": full}
-
-
-def versions_from_parentdir(parentdir_prefix, versionfile_source, verbose=False):
- if IN_LONG_VERSION_PY:
- # We're running from _version.py. If it's from a source tree
- # (execute-in-place), we can work upwards to find the root of the
- # tree, and then check the parent directory for a version string. If
- # it's in an installed application, there's no hope.
- try:
- here = os.path.abspath(__file__)
- except NameError:
- # py2exe/bbfreeze/non-CPython don't have __file__
- return {} # without __file__, we have no hope
- # versionfile_source is the relative path from the top of the source
- # tree to _version.py. Invert this to find the root from __file__.
- root = here
- for i in range(len(versionfile_source.split("/"))):
- root = os.path.dirname(root)
+ GITS = ["git.cmd", "git.exe"]
+ # if there is a tag, this yields TAG-NUM-gHEX[-dirty]
+ # if there are no tags, this yields HEX[-dirty] (no NUM)
+ describe_out = run_command(GITS, ["describe", "--tags", "--dirty",
+ "--always", "--long"],
+ cwd=root)
+ # --long was added in git-1.5.5
+ if describe_out is None:
+ raise NotThisMethod("'git describe' failed")
+ describe_out = describe_out.strip()
+ full_out = run_command(GITS, ["rev-parse", "HEAD"], cwd=root)
+ if full_out is None:
+ raise NotThisMethod("'git rev-parse' failed")
+ full_out = full_out.strip()
+
+ pieces = {}
+ pieces["long"] = full_out
+ pieces["short"] = full_out[:7] # maybe improved later
+ pieces["error"] = None
+
+ # parse describe_out. It will be like TAG-NUM-gHEX[-dirty] or HEX[-dirty]
+ # TAG might have hyphens.
+ git_describe = describe_out
+
+ # look for -dirty suffix
+ dirty = git_describe.endswith("-dirty")
+ pieces["dirty"] = dirty
+ if dirty:
+ git_describe = git_describe[:git_describe.rindex("-dirty")]
+
+ # now we have TAG-NUM-gHEX or HEX
+
+ if "-" in git_describe:
+ # TAG-NUM-gHEX
+ mo = re.search(r'^(.+)-(\d+)-g([0-9a-f]+)$', git_describe)
+ if not mo:
+ # unparseable. Maybe git-describe is misbehaving?
+ pieces["error"] = ("unable to parse git-describe output: '%s'"
+ % describe_out)
+ return pieces
+
+ # tag
+ full_tag = mo.group(1)
+ if not full_tag.startswith(tag_prefix):
+ if verbose:
+ fmt = "tag '%s' doesn't start with prefix '%s'"
+ print(fmt % (full_tag, tag_prefix))
+ pieces["error"] = ("tag '%s' doesn't start with prefix '%s'"
+ % (full_tag, tag_prefix))
+ return pieces
+ pieces["closest-tag"] = full_tag[len(tag_prefix):]
+
+ # distance: number of commits since tag
+ pieces["distance"] = int(mo.group(2))
+
+ # commit: short hex revision ID
+ pieces["short"] = mo.group(3)
+
else:
- # we're running from versioneer.py, which means we're running from
- # the setup.py in a source tree. sys.argv[0] is setup.py in the root.
- here = os.path.abspath(sys.argv[0])
- root = os.path.dirname(here)
+ # HEX: no tags
+ pieces["closest-tag"] = None
+ count_out = run_command(GITS, ["rev-list", "HEAD", "--count"],
+ cwd=root)
+ pieces["distance"] = int(count_out) # total number of commits
- # Source tarballs conventionally unpack into a directory that includes
- # both the project name and a version string.
- dirname = os.path.basename(root)
- if not dirname.startswith(parentdir_prefix):
- if verbose:
- print("guessing rootdir is '%s', but '%s' doesn't start with prefix '%s'" %
- (root, dirname, parentdir_prefix))
- return None
- return {"version": dirname[len(parentdir_prefix):], "full": ""}
+ return pieces
-import sys
-def do_vcs_install(versionfile_source, ipy):
- GIT = "git"
+def do_vcs_install(manifest_in, versionfile_source, ipy):
+ GITS = ["git"]
if sys.platform == "win32":
- GIT = "git.exe"
- run_command([GIT, "add", "versioneer.py"])
- run_command([GIT, "add", versionfile_source])
- run_command([GIT, "add", ipy])
+ GITS = ["git.cmd", "git.exe"]
+ files = [manifest_in, versionfile_source]
+ if ipy:
+ files.append(ipy)
+ try:
+ me = __file__
+ if me.endswith(".pyc") or me.endswith(".pyo"):
+ me = os.path.splitext(me)[0] + ".py"
+ versioneer_file = os.path.relpath(me)
+ except NameError:
+ versioneer_file = "versioneer.py"
+ files.append(versioneer_file)
present = False
try:
f = open(".gitattributes", "r")
@@ -494,135 +1107,465 @@ def do_vcs_install(versionfile_source, ipy):
f = open(".gitattributes", "a+")
f.write("%s export-subst\n" % versionfile_source)
f.close()
- run_command([GIT, "add", ".gitattributes"])
+ files.append(".gitattributes")
+ run_command(GITS, ["add", "--"] + files)
+def versions_from_parentdir(parentdir_prefix, root, verbose):
+ # Source tarballs conventionally unpack into a directory that includes
+ # both the project name and a version string.
+ dirname = os.path.basename(root)
+ if not dirname.startswith(parentdir_prefix):
+ if verbose:
+ print("guessing rootdir is '%s', but '%s' doesn't start with "
+ "prefix '%s'" % (root, dirname, parentdir_prefix))
+ raise NotThisMethod("rootdir doesn't start with parentdir_prefix")
+ return {"version": dirname[len(parentdir_prefix):],
+ "full-revisionid": None,
+ "dirty": False, "error": None}
+
SHORT_VERSION_PY = """
-# This file was generated by 'versioneer.py' (0.7+) from
+# This file was generated by 'versioneer.py' (0.15) from
# revision-control system data, or from the parent directory name of an
# unpacked source archive. Distribution tarballs contain a pre-generated copy
# of this file.
-version_version = '%(version)s'
-version_full = '%(full)s'
-def get_versions(default={}, verbose=False):
- return {'version': version_version, 'full': version_full}
+import json
+import sys
+
+version_json = '''
+%s
+''' # END VERSION_JSON
+
+def get_versions():
+ return json.loads(version_json)
"""
-DEFAULT = {"version": "unknown", "full": "unknown"}
def versions_from_file(filename):
- versions = {}
try:
- f = open(filename)
+ with open(filename) as f:
+ contents = f.read()
except EnvironmentError:
- return versions
- for line in f.readlines():
- mo = re.match("version_version = '([^']+)'", line)
- if mo:
- versions["version"] = mo.group(1)
- mo = re.match("version_full = '([^']+)'", line)
- if mo:
- versions["full"] = mo.group(1)
- f.close()
- return versions
+ raise NotThisMethod("unable to read _version.py")
+ mo = re.search(r"version_json = '''\n(.*)''' # END VERSION_JSON",
+ contents, re.M | re.S)
+ if not mo:
+ raise NotThisMethod("no version_json in _version.py")
+ return json.loads(mo.group(1))
+
def write_to_version_file(filename, versions):
- f = open(filename, "w")
- f.write(SHORT_VERSION_PY % versions)
- f.close()
+ os.unlink(filename)
+ contents = json.dumps(versions, sort_keys=True,
+ indent=1, separators=(",", ": "))
+ with open(filename, "w") as f:
+ f.write(SHORT_VERSION_PY % contents)
+
print("set %s to '%s'" % (filename, versions["version"]))
-def get_best_versions(versionfile, tag_prefix, parentdir_prefix,
- default=DEFAULT, verbose=False):
+def plus_or_dot(pieces):
+ if "+" in pieces.get("closest-tag", ""):
+ return "."
+ return "+"
+
+
+def render_pep440(pieces):
+ # now build up version string, with post-release "local version
+ # identifier". Our goal: TAG[+DISTANCE.gHEX[.dirty]] . Note that if you
+ # get a tagged build and then dirty it, you'll get TAG+0.gHEX.dirty
+
+ # exceptions:
+ # 1: no tags. git_describe was just HEX. 0+untagged.DISTANCE.gHEX[.dirty]
+
+ if pieces["closest-tag"]:
+ rendered = pieces["closest-tag"]
+ if pieces["distance"] or pieces["dirty"]:
+ rendered += plus_or_dot(pieces)
+ rendered += "%d.g%s" % (pieces["distance"], pieces["short"])
+ if pieces["dirty"]:
+ rendered += ".dirty"
+ else:
+ # exception #1
+ rendered = "0+untagged.%d.g%s" % (pieces["distance"],
+ pieces["short"])
+ if pieces["dirty"]:
+ rendered += ".dirty"
+ return rendered
+
+
+def render_pep440_pre(pieces):
+ # TAG[.post.devDISTANCE] . No -dirty
+
+ # exceptions:
+ # 1: no tags. 0.post.devDISTANCE
+
+ if pieces["closest-tag"]:
+ rendered = pieces["closest-tag"]
+ if pieces["distance"]:
+ rendered += ".post.dev%d" % pieces["distance"]
+ else:
+ # exception #1
+ rendered = "0.post.dev%d" % pieces["distance"]
+ return rendered
+
+
+def render_pep440_post(pieces):
+ # TAG[.postDISTANCE[.dev0]+gHEX] . The ".dev0" means dirty. Note that
+ # .dev0 sorts backwards (a dirty tree will appear "older" than the
+ # corresponding clean one), but you shouldn't be releasing software with
+ # -dirty anyways.
+
+ # exceptions:
+ # 1: no tags. 0.postDISTANCE[.dev0]
+
+ if pieces["closest-tag"]:
+ rendered = pieces["closest-tag"]
+ if pieces["distance"] or pieces["dirty"]:
+ rendered += ".post%d" % pieces["distance"]
+ if pieces["dirty"]:
+ rendered += ".dev0"
+ rendered += plus_or_dot(pieces)
+ rendered += "g%s" % pieces["short"]
+ else:
+ # exception #1
+ rendered = "0.post%d" % pieces["distance"]
+ if pieces["dirty"]:
+ rendered += ".dev0"
+ rendered += "+g%s" % pieces["short"]
+ return rendered
+
+
+def render_pep440_old(pieces):
+ # TAG[.postDISTANCE[.dev0]] . The ".dev0" means dirty.
+
+ # exceptions:
+ # 1: no tags. 0.postDISTANCE[.dev0]
+
+ if pieces["closest-tag"]:
+ rendered = pieces["closest-tag"]
+ if pieces["distance"] or pieces["dirty"]:
+ rendered += ".post%d" % pieces["distance"]
+ if pieces["dirty"]:
+ rendered += ".dev0"
+ else:
+ # exception #1
+ rendered = "0.post%d" % pieces["distance"]
+ if pieces["dirty"]:
+ rendered += ".dev0"
+ return rendered
+
+
+def render_git_describe(pieces):
+ # TAG[-DISTANCE-gHEX][-dirty], like 'git describe --tags --dirty
+ # --always'
+
+ # exceptions:
+ # 1: no tags. HEX[-dirty] (note: no 'g' prefix)
+
+ if pieces["closest-tag"]:
+ rendered = pieces["closest-tag"]
+ if pieces["distance"]:
+ rendered += "-%d-g%s" % (pieces["distance"], pieces["short"])
+ else:
+ # exception #1
+ rendered = pieces["short"]
+ if pieces["dirty"]:
+ rendered += "-dirty"
+ return rendered
+
+
+def render_git_describe_long(pieces):
+ # TAG-DISTANCE-gHEX[-dirty], like 'git describe --tags --dirty
+ # --always -long'. The distance/hash is unconditional.
+
+ # exceptions:
+ # 1: no tags. HEX[-dirty] (note: no 'g' prefix)
+
+ if pieces["closest-tag"]:
+ rendered = pieces["closest-tag"]
+ rendered += "-%d-g%s" % (pieces["distance"], pieces["short"])
+ else:
+ # exception #1
+ rendered = pieces["short"]
+ if pieces["dirty"]:
+ rendered += "-dirty"
+ return rendered
+
+
+def render(pieces, style):
+ if pieces["error"]:
+ return {"version": "unknown",
+ "full-revisionid": pieces.get("long"),
+ "dirty": None,
+ "error": pieces["error"]}
+
+ if not style or style == "default":
+ style = "pep440" # the default
+
+ if style == "pep440":
+ rendered = render_pep440(pieces)
+ elif style == "pep440-pre":
+ rendered = render_pep440_pre(pieces)
+ elif style == "pep440-post":
+ rendered = render_pep440_post(pieces)
+ elif style == "pep440-old":
+ rendered = render_pep440_old(pieces)
+ elif style == "git-describe":
+ rendered = render_git_describe(pieces)
+ elif style == "git-describe-long":
+ rendered = render_git_describe_long(pieces)
+ else:
+ raise ValueError("unknown style '%s'" % style)
+
+ return {"version": rendered, "full-revisionid": pieces["long"],
+ "dirty": pieces["dirty"], "error": None}
+
+
+class VersioneerBadRootError(Exception):
+ pass
+
+
+def get_versions(verbose=False):
# returns dict with two keys: 'version' and 'full'
- #
- # extract version from first of _version.py, 'git describe', parentdir.
- # This is meant to work for developers using a source checkout, for users
- # of a tarball created by 'setup.py sdist', and for users of a
- # tarball/zipball created by 'git archive' or github's download-from-tag
- # feature.
-
- variables = get_expanded_variables(versionfile_source)
- if variables:
- ver = versions_from_expanded_variables(variables, tag_prefix)
- if ver:
- if verbose: print("got version from expanded variable %s" % ver)
- return ver
- ver = versions_from_file(versionfile)
- if ver:
- if verbose: print("got version from file %s %s" % (versionfile, ver))
- return ver
+ if "versioneer" in sys.modules:
+ # see the discussion in cmdclass.py:get_cmdclass()
+ del sys.modules["versioneer"]
- ver = versions_from_vcs(tag_prefix, versionfile_source, verbose)
- if ver:
- if verbose: print("got version from git %s" % ver)
- return ver
+ root = get_root()
+ cfg = get_config_from_root(root)
- ver = versions_from_parentdir(parentdir_prefix, versionfile_source, verbose)
- if ver:
- if verbose: print("got version from parentdir %s" % ver)
- return ver
+ assert cfg.VCS is not None, "please set [versioneer]VCS= in setup.cfg"
+ handlers = HANDLERS.get(cfg.VCS)
+ assert handlers, "unrecognized VCS '%s'" % cfg.VCS
+ verbose = verbose or cfg.verbose
+ assert cfg.versionfile_source is not None, \
+ "please set versioneer.versionfile_source"
+ assert cfg.tag_prefix is not None, "please set versioneer.tag_prefix"
+
+ versionfile_abs = os.path.join(root, cfg.versionfile_source)
- if verbose: print("got version from default %s" % ver)
- return default
-
-def get_versions(default=DEFAULT, verbose=False):
- assert versionfile_source is not None, "please set versioneer.versionfile_source"
- assert tag_prefix is not None, "please set versioneer.tag_prefix"
- assert parentdir_prefix is not None, "please set versioneer.parentdir_prefix"
- return get_best_versions(versionfile_source, tag_prefix, parentdir_prefix,
- default=default, verbose=verbose)
-def get_version(verbose=False):
- return get_versions(verbose=verbose)["version"]
-
-class cmd_version(Command):
- description = "report generated version string"
- user_options = []
- boolean_options = []
- def initialize_options(self):
+ # extract version from first of: _version.py, VCS command (e.g. 'git
+ # describe'), parentdir. This is meant to work for developers using a
+ # source checkout, for users of a tarball created by 'setup.py sdist',
+ # and for users of a tarball/zipball created by 'git archive' or github's
+ # download-from-tag feature or the equivalent in other VCSes.
+
+ get_keywords_f = handlers.get("get_keywords")
+ from_keywords_f = handlers.get("keywords")
+ if get_keywords_f and from_keywords_f:
+ try:
+ keywords = get_keywords_f(versionfile_abs)
+ ver = from_keywords_f(keywords, cfg.tag_prefix, verbose)
+ if verbose:
+ print("got version from expanded keyword %s" % ver)
+ return ver
+ except NotThisMethod:
+ pass
+
+ try:
+ ver = versions_from_file(versionfile_abs)
+ if verbose:
+ print("got version from file %s %s" % (versionfile_abs, ver))
+ return ver
+ except NotThisMethod:
pass
- def finalize_options(self):
+
+ from_vcs_f = handlers.get("pieces_from_vcs")
+ if from_vcs_f:
+ try:
+ pieces = from_vcs_f(cfg.tag_prefix, root, verbose)
+ ver = render(pieces, cfg.style)
+ if verbose:
+ print("got version from VCS %s" % ver)
+ return ver
+ except NotThisMethod:
+ pass
+
+ try:
+ if cfg.parentdir_prefix:
+ ver = versions_from_parentdir(cfg.parentdir_prefix, root, verbose)
+ if verbose:
+ print("got version from parentdir %s" % ver)
+ return ver
+ except NotThisMethod:
pass
- def run(self):
- ver = get_version(verbose=True)
- print("Version is currently: %s" % ver)
-
-
-class cmd_build(_build):
- def run(self):
- versions = get_versions(verbose=True)
- _build.run(self)
- # now locate _version.py in the new build/ directory and replace it
- # with an updated value
- target_versionfile = os.path.join(self.build_lib, versionfile_build)
- print("UPDATING %s" % target_versionfile)
- os.unlink(target_versionfile)
- f = open(target_versionfile, "w")
- f.write(SHORT_VERSION_PY % versions)
- f.close()
-class cmd_sdist(_sdist):
- def run(self):
- versions = get_versions(verbose=True)
- self._versioneer_generated_versions = versions
- # unless we update this, the command will keep using the old version
- self.distribution.metadata.version = versions["version"]
- return _sdist.run(self)
-
- def make_release_tree(self, base_dir, files):
- _sdist.make_release_tree(self, base_dir, files)
- # now locate _version.py in the new base_dir directory (remembering
- # that it may be a hardlink) and replace it with an updated value
- target_versionfile = os.path.join(base_dir, versionfile_source)
- print("UPDATING %s" % target_versionfile)
- os.unlink(target_versionfile)
- f = open(target_versionfile, "w")
- f.write(SHORT_VERSION_PY % self._versioneer_generated_versions)
- f.close()
+ if verbose:
+ print("unable to compute version")
+
+ return {"version": "0+unknown", "full-revisionid": None,
+ "dirty": None, "error": "unable to compute version"}
+
+
+def get_version():
+ return get_versions()["version"]
+
+
+def get_cmdclass():
+ if "versioneer" in sys.modules:
+ del sys.modules["versioneer"]
+ # this fixes the "python setup.py develop" case (also 'install' and
+ # 'easy_install .'), in which subdependencies of the main project are
+ # built (using setup.py bdist_egg) in the same python process. Assume
+ # a main project A and a dependency B, which use different versions
+ # of Versioneer. A's setup.py imports A's Versioneer, leaving it in
+ # sys.modules by the time B's setup.py is executed, causing B to run
+ # with the wrong versioneer. Setuptools wraps the sub-dep builds in a
+ # sandbox that restores sys.modules to it's pre-build state, so the
+ # parent is protected against the child's "import versioneer". By
+ # removing ourselves from sys.modules here, before the child build
+ # happens, we protect the child from the parent's versioneer too.
+ # Also see https://github.com/warner/python-versioneer/issues/52
+
+ cmds = {}
+
+ # we add "version" to both distutils and setuptools
+ from distutils.core import Command
+
+ class cmd_version(Command):
+ description = "report generated version string"
+ user_options = []
+ boolean_options = []
+
+ def initialize_options(self):
+ pass
+
+ def finalize_options(self):
+ pass
+
+ def run(self):
+ vers = get_versions(verbose=True)
+ print("Version: %s" % vers["version"])
+ print(" full-revisionid: %s" % vers.get("full-revisionid"))
+ print(" dirty: %s" % vers.get("dirty"))
+ if vers["error"]:
+ print(" error: %s" % vers["error"])
+ cmds["version"] = cmd_version
+
+ # we override "build_py" in both distutils and setuptools
+ #
+ # most invocation pathways end up running build_py:
+ # distutils/build -> build_py
+ # distutils/install -> distutils/build ->..
+ # setuptools/bdist_wheel -> distutils/install ->..
+ # setuptools/bdist_egg -> distutils/install_lib -> build_py
+ # setuptools/install -> bdist_egg ->..
+ # setuptools/develop -> ?
+
+ from distutils.command.build_py import build_py as _build_py
+
+ class cmd_build_py(_build_py):
+ def run(self):
+ root = get_root()
+ cfg = get_config_from_root(root)
+ versions = get_versions()
+ _build_py.run(self)
+ # now locate _version.py in the new build/ directory and replace
+ # it with an updated value
+ if cfg.versionfile_build:
+ target_versionfile = os.path.join(self.build_lib,
+ cfg.versionfile_build)
+ print("UPDATING %s" % target_versionfile)
+ write_to_version_file(target_versionfile, versions)
+ cmds["build_py"] = cmd_build_py
+
+ if "cx_Freeze" in sys.modules: # cx_freeze enabled?
+ from cx_Freeze.dist import build_exe as _build_exe
+
+ class cmd_build_exe(_build_exe):
+ def run(self):
+ root = get_root()
+ cfg = get_config_from_root(root)
+ versions = get_versions()
+ target_versionfile = cfg.versionfile_source
+ print("UPDATING %s" % target_versionfile)
+ write_to_version_file(target_versionfile, versions)
+
+ _build_exe.run(self)
+ os.unlink(target_versionfile)
+ with open(cfg.versionfile_source, "w") as f:
+ LONG = LONG_VERSION_PY[cfg.VCS]
+ f.write(LONG %
+ {"DOLLAR": "$",
+ "STYLE": cfg.style,
+ "TAG_PREFIX": cfg.tag_prefix,
+ "PARENTDIR_PREFIX": cfg.parentdir_prefix,
+ "VERSIONFILE_SOURCE": cfg.versionfile_source,
+ })
+ cmds["build_exe"] = cmd_build_exe
+ del cmds["build_py"]
+
+ # we override different "sdist" commands for both environments
+ if "setuptools" in sys.modules:
+ from setuptools.command.sdist import sdist as _sdist
+ else:
+ from distutils.command.sdist import sdist as _sdist
+
+ class cmd_sdist(_sdist):
+ def run(self):
+ versions = get_versions()
+ self._versioneer_generated_versions = versions
+ # unless we update this, the command will keep using the old
+ # version
+ self.distribution.metadata.version = versions["version"]
+ return _sdist.run(self)
+
+ def make_release_tree(self, base_dir, files):
+ root = get_root()
+ cfg = get_config_from_root(root)
+ _sdist.make_release_tree(self, base_dir, files)
+ # now locate _version.py in the new base_dir directory
+ # (remembering that it may be a hardlink) and replace it with an
+ # updated value
+ target_versionfile = os.path.join(base_dir, cfg.versionfile_source)
+ print("UPDATING %s" % target_versionfile)
+ write_to_version_file(target_versionfile,
+ self._versioneer_generated_versions)
+ cmds["sdist"] = cmd_sdist
+
+ return cmds
+
+
+CONFIG_ERROR = """
+setup.cfg is missing the necessary Versioneer configuration. You need
+a section like:
+
+ [versioneer]
+ VCS = git
+ style = pep440
+ versionfile_source = src/myproject/_version.py
+ versionfile_build = myproject/_version.py
+ tag_prefix = ""
+ parentdir_prefix = myproject-
+
+You will also need to edit your setup.py to use the results:
+
+ import versioneer
+ setup(version=versioneer.get_version(),
+ cmdclass=versioneer.get_cmdclass(), ...)
+
+Please read the docstring in ./versioneer.py for configuration instructions,
+edit setup.cfg, and re-run the installer or 'python versioneer.py setup'.
+"""
+
+SAMPLE_CONFIG = """
+# See the docstring in versioneer.py for instructions. Note that you must
+# re-run 'versioneer.py setup' after changing this section, and commit the
+# resulting files.
+
+[versioneer]
+#VCS = git
+#style = pep440
+#versionfile_source =
+#versionfile_build =
+#tag_prefix =
+#parentdir_prefix =
+
+"""
INIT_PY_SNIPPET = """
from ._version import get_versions
@@ -630,40 +1573,127 @@ __version__ = get_versions()['version']
del get_versions
"""
-class cmd_update_files(Command):
- description = "modify __init__.py and create _version.py"
- user_options = []
- boolean_options = []
- def initialize_options(self):
- pass
- def finalize_options(self):
- pass
- def run(self):
- ipy = os.path.join(os.path.dirname(versionfile_source), "__init__.py")
- print(" creating %s" % versionfile_source)
- f = open(versionfile_source, "w")
- f.write(LONG_VERSION_PY % {"DOLLAR": "$",
- "TAG_PREFIX": tag_prefix,
- "PARENTDIR_PREFIX": parentdir_prefix,
- "VERSIONFILE_SOURCE": versionfile_source,
- })
- f.close()
+
+def do_setup():
+ root = get_root()
+ try:
+ cfg = get_config_from_root(root)
+ except (EnvironmentError, configparser.NoSectionError,
+ configparser.NoOptionError) as e:
+ if isinstance(e, (EnvironmentError, configparser.NoSectionError)):
+ print("Adding sample versioneer config to setup.cfg",
+ file=sys.stderr)
+ with open(os.path.join(root, "setup.cfg"), "a") as f:
+ f.write(SAMPLE_CONFIG)
+ print(CONFIG_ERROR, file=sys.stderr)
+ return 1
+
+ print(" creating %s" % cfg.versionfile_source)
+ with open(cfg.versionfile_source, "w") as f:
+ LONG = LONG_VERSION_PY[cfg.VCS]
+ f.write(LONG % {"DOLLAR": "$",
+ "STYLE": cfg.style,
+ "TAG_PREFIX": cfg.tag_prefix,
+ "PARENTDIR_PREFIX": cfg.parentdir_prefix,
+ "VERSIONFILE_SOURCE": cfg.versionfile_source,
+ })
+
+ ipy = os.path.join(os.path.dirname(cfg.versionfile_source),
+ "__init__.py")
+ if os.path.exists(ipy):
try:
- old = open(ipy, "r").read()
+ with open(ipy, "r") as f:
+ old = f.read()
except EnvironmentError:
old = ""
if INIT_PY_SNIPPET not in old:
print(" appending to %s" % ipy)
- f = open(ipy, "a")
- f.write(INIT_PY_SNIPPET)
- f.close()
+ with open(ipy, "a") as f:
+ f.write(INIT_PY_SNIPPET)
else:
print(" %s unmodified" % ipy)
- do_vcs_install(versionfile_source, ipy)
+ else:
+ print(" %s doesn't exist, ok" % ipy)
+ ipy = None
+
+ # Make sure both the top-level "versioneer.py" and versionfile_source
+ # (PKG/_version.py, used by runtime code) are in MANIFEST.in, so
+ # they'll be copied into source distributions. Pip won't be able to
+ # install the package without this.
+ manifest_in = os.path.join(root, "MANIFEST.in")
+ simple_includes = set()
+ try:
+ with open(manifest_in, "r") as f:
+ for line in f:
+ if line.startswith("include "):
+ for include in line.split()[1:]:
+ simple_includes.add(include)
+ except EnvironmentError:
+ pass
+ # That doesn't cover everything MANIFEST.in can do
+ # (http://docs.python.org/2/distutils/sourcedist.html#commands), so
+ # it might give some false negatives. Appending redundant 'include'
+ # lines is safe, though.
+ if "versioneer.py" not in simple_includes:
+ print(" appending 'versioneer.py' to MANIFEST.in")
+ with open(manifest_in, "a") as f:
+ f.write("include versioneer.py\n")
+ else:
+ print(" 'versioneer.py' already in MANIFEST.in")
+ if cfg.versionfile_source not in simple_includes:
+ print(" appending versionfile_source ('%s') to MANIFEST.in" %
+ cfg.versionfile_source)
+ with open(manifest_in, "a") as f:
+ f.write("include %s\n" % cfg.versionfile_source)
+ else:
+ print(" versionfile_source already in MANIFEST.in")
-def get_cmdclass():
- return {'version': cmd_version,
- 'update_files': cmd_update_files,
- 'build': cmd_build,
- 'sdist': cmd_sdist,
- }
+ # Make VCS-specific changes. For git, this means creating/changing
+ # .gitattributes to mark _version.py for export-time keyword
+ # substitution.
+ do_vcs_install(manifest_in, cfg.versionfile_source, ipy)
+ return 0
+
+
+def scan_setup_py():
+ found = set()
+ setters = False
+ errors = 0
+ with open("setup.py", "r") as f:
+ for line in f.readlines():
+ if "import versioneer" in line:
+ found.add("import")
+ if "versioneer.get_cmdclass()" in line:
+ found.add("cmdclass")
+ if "versioneer.get_version()" in line:
+ found.add("get_version")
+ if "versioneer.VCS" in line:
+ setters = True
+ if "versioneer.versionfile_source" in line:
+ setters = True
+ if len(found) != 3:
+ print("")
+ print("Your setup.py appears to be missing some important items")
+ print("(but I might be wrong). Please make sure it has something")
+ print("roughly like the following:")
+ print("")
+ print(" import versioneer")
+ print(" setup( version=versioneer.get_version(),")
+ print(" cmdclass=versioneer.get_cmdclass(), ...)")
+ print("")
+ errors += 1
+ if setters:
+ print("You should remove lines like 'versioneer.VCS = ' and")
+ print("'versioneer.versionfile_source = ' . This configuration")
+ print("now lives in setup.cfg, and should be removed from setup.py")
+ print("")
+ errors += 1
+ return errors
+
+if __name__ == "__main__":
+ cmd = sys.argv[1]
+ if cmd == "setup":
+ errors = do_setup()
+ errors += scan_setup_py()
+ if errors:
+ sys.exit(1)
--
cgit v1.2.3
From 470d24ec886adedae6d47e684ab1dc14aa2c21ea Mon Sep 17 00:00:00 2001
From: Kali Kaneko
Date: Fri, 4 Mar 2016 11:28:30 -0400
Subject: [style] pep8
---
src/leap/bitmask/_version.py | 2 +-
versioneer.py | 5 ++++-
2 files changed, 5 insertions(+), 2 deletions(-)
diff --git a/src/leap/bitmask/_version.py b/src/leap/bitmask/_version.py
index 93700af1..8c507c92 100644
--- a/src/leap/bitmask/_version.py
+++ b/src/leap/bitmask/_version.py
@@ -155,7 +155,7 @@ def git_versions_from_keywords(keywords, tag_prefix, verbose):
# "stabilization", as well as "HEAD" and "master".
tags = set([r for r in refs if re.search(r'\d', r)])
if verbose:
- print("discarding '%s', no digits" % ",".join(refs-tags))
+ print("discarding '%s', no digits" % ",".join(refs - tags))
if verbose:
print("likely tags: %s" % ",".join(sorted(tags)))
for ref in sorted(tags):
diff --git a/versioneer.py b/versioneer.py
index c010f63e..89194938 100644
--- a/versioneer.py
+++ b/versioneer.py
@@ -975,7 +975,7 @@ def git_versions_from_keywords(keywords, tag_prefix, verbose):
# "stabilization", as well as "HEAD" and "master".
tags = set([r for r in refs if re.search(r'\d', r)])
if verbose:
- print("discarding '%s', no digits" % ",".join(refs-tags))
+ print("discarding '%s', no digits" % ",".join(refs - tags))
if verbose:
print("likely tags: %s" % ",".join(sorted(tags)))
for ref in sorted(tags):
@@ -1459,6 +1459,7 @@ def get_cmdclass():
from distutils.command.build_py import build_py as _build_py
class cmd_build_py(_build_py):
+
def run(self):
root = get_root()
cfg = get_config_from_root(root)
@@ -1477,6 +1478,7 @@ def get_cmdclass():
from cx_Freeze.dist import build_exe as _build_exe
class cmd_build_exe(_build_exe):
+
def run(self):
root = get_root()
cfg = get_config_from_root(root)
@@ -1506,6 +1508,7 @@ def get_cmdclass():
from distutils.command.sdist import sdist as _sdist
class cmd_sdist(_sdist):
+
def run(self):
versions = get_versions()
self._versioneer_generated_versions = versions
--
cgit v1.2.3
From 3d2df02b549a32c15b2bb369a33789abadb60c92 Mon Sep 17 00:00:00 2001
From: Kali Kaneko
Date: Fri, 4 Mar 2016 11:44:18 -0400
Subject: [bug] fix some version handling errors
---
setup.py | 11 ++++++-----
src/leap/bitmask/__init__.py | 6 +++++-
src/leap/bitmask/provider/__init__.py | 2 +-
3 files changed, 12 insertions(+), 7 deletions(-)
diff --git a/setup.py b/setup.py
index e85c4564..fc9c36c9 100755
--- a/setup.py
+++ b/setup.py
@@ -24,7 +24,8 @@ import hashlib
import sys
import os
import re
-import sys
+
+from distutils.command.build import build as _build
if not sys.version_info[0] == 2:
print("[ERROR] Sorry, Python 3 is not supported (yet). "
@@ -259,16 +260,16 @@ BITMASK_ROOT = "{bitmask}"
cmdclass["hash_binaries"] = cmd_binary_hash
-# next two classes need to augment the versioneer modified ones
+# sdist class need to augment the versioneer modified ones
-versioneer_build = cmdclass['build_py']
+#_build = cmdclass['build_py']
versioneer_sdist = cmdclass['sdist']
-class cmd_build(versioneer_build):
+class cmd_build(_build):
def run(self):
- versioneer_build.run(self)
+ _build.run(self)
copy_reqs(self.build_lib)
diff --git a/src/leap/bitmask/__init__.py b/src/leap/bitmask/__init__.py
index 966ce91e..6ab55e53 100644
--- a/src/leap/bitmask/__init__.py
+++ b/src/leap/bitmask/__init__.py
@@ -38,11 +38,15 @@ def _is_release_version(version_str):
:rtype: bool
"""
parts = __version__.split('.')
- patch = parts[2]
+ try:
+ patch = parts[2]
+ except IndexError:
+ return False
return patch.isdigit()
from ._version import get_versions
__version__ = get_versions()['version']
+__version_hash__ = get_versions()['full-revisionid']
IS_RELEASE_VERSION = _is_release_version(__version__)
del get_versions
diff --git a/src/leap/bitmask/provider/__init__.py b/src/leap/bitmask/provider/__init__.py
index 4385a92f..60a41181 100644
--- a/src/leap/bitmask/provider/__init__.py
+++ b/src/leap/bitmask/provider/__init__.py
@@ -22,7 +22,7 @@ import os
from pkg_resources import parse_version
-from leap.bitmask import __short_version__ as BITMASK_VERSION
+from leap.bitmask import __version__ as BITMASK_VERSION
from leap.common.check import leap_assert
logger = logging.getLogger(__name__)
--
cgit v1.2.3
From 21a0e07ffccbee57fa02f20525441f96516132dc Mon Sep 17 00:00:00 2001
From: Kali Kaneko
Date: Mon, 21 Mar 2016 15:52:43 -0400
Subject: [bug] re-download smtp certificate if needed.
the should_redownload function was only called if the pemfile was not
present of the fs.
- Resolves: #7869
---
changes/next-changelog.rst | 4 +++-
src/leap/bitmask/services/mail/smtpbootstrapper.py | 9 +++++----
2 files changed, 8 insertions(+), 5 deletions(-)
diff --git a/changes/next-changelog.rst b/changes/next-changelog.rst
index 64774d30..d07273ec 100644
--- a/changes/next-changelog.rst
+++ b/changes/next-changelog.rst
@@ -24,8 +24,10 @@ Bugfixes
- `#7583 `_: Fix set_soledad_auth_token event callback signature.
- `#7585 `_: Open email help link on browser.
- `#7598 `_: Fix errback on InvalidAuthToken.
-- `#1235 `_: Description for the fixed stuff corresponding with issue #1235.
+- `#7869 `_: Redownload smtp certificate if needed.
- Do not translate 'https' text on QLabel.
+
+- `#1235 `_: Description for the fixed stuff corresponding with issue #1235.
- Bugfix without related issue number.
Misc
diff --git a/src/leap/bitmask/services/mail/smtpbootstrapper.py b/src/leap/bitmask/services/mail/smtpbootstrapper.py
index dadf59dd..f73687a7 100644
--- a/src/leap/bitmask/services/mail/smtpbootstrapper.py
+++ b/src/leap/bitmask/services/mail/smtpbootstrapper.py
@@ -29,7 +29,6 @@ from leap.bitmask.logs.utils import get_logger
from leap.bitmask.services import download_service_config
from leap.bitmask.services.abstractbootstrapper import AbstractBootstrapper
from leap.bitmask.services.mail.smtpconfig import SMTPConfig
-from leap.bitmask.util import is_file
from leap.common import certs as leap_certs
from leap.common.check import leap_assert
@@ -93,11 +92,13 @@ class SMTPBootstrapper(AbstractBootstrapper):
client_cert_path = self._smtp_config.get_client_cert_path(
self._userid, self._provider_config, about_to_download=True)
- if not is_file(client_cert_path):
+ needs_download = leap_certs.should_redownload(client_cert_path)
+
+ if needs_download:
# For re-download if something is wrong with the cert
+ # FIXME this doesn't read well. should reword the logic here.
self._download_if_needed = (
- self._download_if_needed and
- not leap_certs.should_redownload(client_cert_path))
+ self._download_if_needed and not needs_download)
if self._download_if_needed and os.path.isfile(client_cert_path):
check_and_fix_urw_only(client_cert_path)
--
cgit v1.2.3
From b596eab3591414c4ef58648d74434bc0d5d7c6e3 Mon Sep 17 00:00:00 2001
From: Kali Kaneko
Date: Wed, 23 Mar 2016 11:52:44 -0400
Subject: [feature] pixelated adaptor
---
src/leap/bitmask/pix.py | 145 ++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 145 insertions(+)
create mode 100644 src/leap/bitmask/pix.py
diff --git a/src/leap/bitmask/pix.py b/src/leap/bitmask/pix.py
new file mode 100644
index 00000000..abc8a822
--- /dev/null
+++ b/src/leap/bitmask/pix.py
@@ -0,0 +1,145 @@
+# -*- coding: utf-8 -*-
+# pix.py
+# Copyright (C) 2016 LEAP
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see .
+"""
+Pixelated plugin integration.
+"""
+import os
+
+from twisted.internet import defer
+from twisted.python import log
+
+from leap.mail.imap.account import IMAPAccount
+
+from pixelated.adapter.mailstore import LeapMailStore
+from pixelated.adapter.welcome_mail import add_welcome_mail
+from pixelated.application import SingleUserServicesFactory
+from pixelated.application import UserAgentMode
+from pixelated.application import start_site
+from pixelated.bitmask_libraries.smtp import LeapSMTPConfig
+from pixelated.bitmask_libraries.session import SessionCache
+from pixelated.config import services
+from pixelated.resources.root_resource import RootResource
+
+
+def start_pixelated_user_agent(userid, soledad, keymanager):
+
+ print 'STARTING PIXELATED USER AGENT...'
+
+ leap_session = LeapSessionAdapter(
+ userid, soledad, keymanager)
+
+ config = Config()
+ leap_home = os.path.expanduser('~/.config/leap')
+ config.leap_home = leap_home
+ leap_session.config = config
+
+ services_factory = SingleUserServicesFactory(
+ UserAgentMode(is_single_user=True))
+ resource = RootResource(services_factory)
+
+ config.port = 9090
+ config.sslkey = None
+ config.sslcert = None
+ config.host = 'localhost'
+
+ deferred = _start_in_single_user_mode(
+ leap_session, config,
+ resource, services_factory)
+ return deferred
+
+
+class LeapSessionAdapter(object):
+
+ def __init__(self, userid, soledad, keymanager):
+ self.userid = userid
+
+ self.soledad = soledad
+
+ self.nicknym = Config()
+ self.nicknym.keymanager = keymanager
+
+ self.mail_store = LeapMailStore(soledad)
+
+ self.user_auth = Config()
+ self.user_auth.uuid = soledad.uuid
+
+ # XXX what is this?? path to smtp-service?
+ # self.config = provider.config
+ # self.provider = provider
+
+ self.fresh_account = False
+ self.incoming_mail_fetcher = None
+ self.account = IMAPAccount(userid, soledad, defer.Deferred())
+
+ username, provider = userid.split('@')
+ smtp_client_cert = os.path.expanduser(
+ '~/.config/leap/providers/{provider}/keys/'
+ 'client/smtp_{username}.pem'.format(
+ provider=provider, username=username))
+ # TODO --- get from config
+ smtp_host = 'antelope.mail.bitmask.net'
+ smtp_port = 2013
+
+ self.smtp_config = LeapSMTPConfig(
+ userid,
+ smtp_client_cert, smtp_host, smtp_port)
+
+ def account_email(self):
+ return self.userid
+
+ def close(self):
+ pass
+
+ @property
+ def is_closed(self):
+ return self._is_closed
+
+ def remove_from_cache(self):
+ key = SessionCache.session_key(self.provider, self.userid)
+ SessionCache.remove_session(key)
+
+ def sync(self):
+ return self.soledad.sync()
+
+
+class Config(object):
+ pass
+
+
+def _start_in_single_user_mode(leap_session, config, resource,
+ services_factory):
+ start_site(config, resource)
+ return start_user_agent_in_single_user_mode(
+ resource, services_factory,
+ leap_session.config.leap_home, leap_session)
+
+
+@defer.inlineCallbacks
+def start_user_agent_in_single_user_mode(
+ root_resource, services_factory, leap_home, leap_session):
+ log.msg('Bootstrap done, loading services for user %s'
+ % leap_session.userid)
+
+ _services = services.Services(leap_session)
+ yield _services.setup()
+
+ if leap_session.fresh_account:
+ yield add_welcome_mail(leap_session.mail_store)
+
+ services_factory.add_session(leap_session.user_auth.uuid, _services)
+ root_resource.initialize()
+ log.msg('Done, the user agent is ready to be used')
--
cgit v1.2.3
From c866892b988912a5b9a88edfd6d1e71491617822 Mon Sep 17 00:00:00 2001
From: Kali Kaneko
Date: Wed, 23 Mar 2016 11:53:15 -0400
Subject: [feature] quick integration with legacy gui
---
src/leap/bitmask/backend/api.py | 2 ++
src/leap/bitmask/backend/components.py | 13 ++++++++++++-
src/leap/bitmask/backend/leapbackend.py | 6 ++++++
src/leap/bitmask/services/mail/conductor.py | 15 ++++++++++++++-
4 files changed, 34 insertions(+), 2 deletions(-)
diff --git a/src/leap/bitmask/backend/api.py b/src/leap/bitmask/backend/api.py
index 134a2d56..2fd983ae 100644
--- a/src/leap/bitmask/backend/api.py
+++ b/src/leap/bitmask/backend/api.py
@@ -42,6 +42,8 @@ API = (
"keymanager_export_keys",
"keymanager_get_key_details",
"keymanager_list_keys",
+ "pixelated_start_service",
+ "pixelated_stop_service",
"provider_bootstrap",
"provider_cancel_setup",
"provider_get_all_services",
diff --git a/src/leap/bitmask/backend/components.py b/src/leap/bitmask/backend/components.py
index d8e4edbf..0f8864c3 100644
--- a/src/leap/bitmask/backend/components.py
+++ b/src/leap/bitmask/backend/components.py
@@ -26,7 +26,7 @@ import time
from functools import partial
-from twisted.internet import threads, defer
+from twisted.internet import threads, defer, reactor
from twisted.python import log
import zope.interface
@@ -38,6 +38,7 @@ from leap.bitmask.crypto.srpauth import SRPAuth
from leap.bitmask.crypto.srpregister import SRPRegister
from leap.bitmask.logs.utils import get_logger
from leap.bitmask.platform_init import IS_LINUX
+from leap.bitmask.pix import start_pixelated_user_agent
from leap.bitmask.provider.pinned import PinnedProviders
from leap.bitmask.provider.providerbootstrapper import ProviderBootstrapper
from leap.bitmask.services import get_supported
@@ -1086,6 +1087,16 @@ class Mail(object):
"""
return threads.deferToThread(self._stop_imap_service)
+ def start_pixelated_service(self, full_user_id):
+ reactor.callFromThread(
+ start_pixelated_user_agent,
+ full_user_id,
+ self._soledad_proxy,
+ self._keymanager_proxy)
+
+ def stop_pixelated_service(self):
+ pass
+
class Authenticate(object):
"""
diff --git a/src/leap/bitmask/backend/leapbackend.py b/src/leap/bitmask/backend/leapbackend.py
index d0668a1c..56b1597c 100644
--- a/src/leap/bitmask/backend/leapbackend.py
+++ b/src/leap/bitmask/backend/leapbackend.py
@@ -531,6 +531,12 @@ class LeapBackend(Backend):
"""
self._mail.stop_imap_service()
+ def pixelated_start_service(self, full_user_id):
+ self._mail.start_pixelated_service(full_user_id)
+
+ def pixelated_stop_service(self):
+ self._mail.stop_pixelated_service()
+
def settings_set_selected_gateway(self, provider, gateway):
"""
Set the selected gateway for a given provider.
diff --git a/src/leap/bitmask/services/mail/conductor.py b/src/leap/bitmask/services/mail/conductor.py
index b94b3cc8..05fafa1a 100644
--- a/src/leap/bitmask/services/mail/conductor.py
+++ b/src/leap/bitmask/services/mail/conductor.py
@@ -192,7 +192,17 @@ class SMTPControl(object):
self.smtp_connection.qtsigs.connection_aborted_signal.emit()
-class MailConductor(IMAPControl, SMTPControl):
+class PixelatedControl(object):
+
+ def start_pixelated_service(self):
+ self._backend.pixelated_start_service(
+ full_user_id=self.userid)
+
+ def stop_pixelated_service(self):
+ pass
+
+
+class MailConductor(IMAPControl, SMTPControl, PixelatedControl):
"""
This class encapsulates everything related to the initialization and
process control for the mail services.
@@ -269,6 +279,9 @@ class MailConductor(IMAPControl, SMTPControl):
self.start_smtp_service(download_if_needed=download_if_needed)
self.start_imap_service()
+ # TODO --- check if it's enabled!!!
+ self.start_pixelated_service()
+
self._mail_services_started = True
def stop_mail_services(self):
--
cgit v1.2.3
From e92e4f1e4d57957af5d8c9e08a6c3c9152409612 Mon Sep 17 00:00:00 2001
From: Kali Kaneko
Date: Wed, 23 Mar 2016 12:03:46 -0400
Subject: [feature] allow to disable pixelmail integration
---
src/leap/bitmask/config/leapsettings.py | 11 ++++++++++-
src/leap/bitmask/services/mail/conductor.py | 7 +++++--
2 files changed, 15 insertions(+), 3 deletions(-)
diff --git a/src/leap/bitmask/config/leapsettings.py b/src/leap/bitmask/config/leapsettings.py
index 484a8a25..a060c8a4 100644
--- a/src/leap/bitmask/config/leapsettings.py
+++ b/src/leap/bitmask/config/leapsettings.py
@@ -70,6 +70,7 @@ class LeapSettings(object):
PINNED_KEY = "Pinned"
SKIPFIRSTRUN_KEY = "SkipFirstRun"
UUIDFORUSER_KEY = "%s/%s_uuid"
+ PIXELMAIL_KEY = "Pixmail"
# values
GATEWAY_AUTOMATIC = "Automatic"
@@ -352,4 +353,12 @@ class LeapSettings(object):
:type skip: bool
"""
leap_assert_type(skip, bool)
- self._settings.setValue(self.SKIPFIRSTRUN_KEY, skip)
+ self._settings.setvalue(self.skipfirstrun_key, skip)
+
+ def get_pixelmail_enabled(self):
+ return to_bool(self._settings.value(self.PIXELMAIL_KEY, False))
+
+ def set_pixelmail_enabled(self, enabled):
+ leap_assert_type(enabled, bool)
+ self._settings.setvalue(self.PIXELMAIL_KEY, enabled)
+
diff --git a/src/leap/bitmask/services/mail/conductor.py b/src/leap/bitmask/services/mail/conductor.py
index 05fafa1a..cccbcf14 100644
--- a/src/leap/bitmask/services/mail/conductor.py
+++ b/src/leap/bitmask/services/mail/conductor.py
@@ -18,6 +18,7 @@
Mail Services Conductor
"""
from leap.bitmask.config import flags
+from leap.bitmask.config.leapsettings import LeapSettings
from leap.bitmask.logs.utils import get_logger
from leap.bitmask.gui import statemachines
from leap.bitmask.services.mail import connection as mail_connection
@@ -279,8 +280,10 @@ class MailConductor(IMAPControl, SMTPControl, PixelatedControl):
self.start_smtp_service(download_if_needed=download_if_needed)
self.start_imap_service()
- # TODO --- check if it's enabled!!!
- self.start_pixelated_service()
+ settings = LeapSettings()
+ pixelmail = settings.get_pixelmail_enabled()
+ if pixelmail:
+ self.start_pixelated_service()
self._mail_services_started = True
--
cgit v1.2.3
From f9cb960dea642ec2e9cced1ab4712577cc0f3469 Mon Sep 17 00:00:00 2001
From: Kali Kaneko
Date: Wed, 23 Mar 2016 19:30:54 -0400
Subject: [feature] add QtWebView to render pixelated mua
---
src/leap/bitmask/gui/mainwindow.py | 8 ++++++++
src/leap/bitmask/gui/qt_browser.py | 13 +++++++++++++
src/leap/bitmask/gui/ui/mainwindow.ui | 6 ++++++
3 files changed, 27 insertions(+)
create mode 100644 src/leap/bitmask/gui/qt_browser.py
diff --git a/src/leap/bitmask/gui/mainwindow.py b/src/leap/bitmask/gui/mainwindow.py
index 759b454f..1f497d2d 100644
--- a/src/leap/bitmask/gui/mainwindow.py
+++ b/src/leap/bitmask/gui/mainwindow.py
@@ -60,6 +60,8 @@ from leap.bitmask.util.keyring_helpers import has_keyring
from leap.common.events import register
from leap.common.events import catalog
+from .qt_browser import PixelatedWindow
+
from leap.mail.imap.service.imap import IMAP_PORT
from ui_mainwindow import Ui_MainWindow
@@ -218,6 +220,8 @@ class MainWindow(QtGui.QMainWindow, SignalTracker):
self._backend_connect()
self.ui.action_preferences.triggered.connect(self._show_preferences)
+ self.ui.action_pixelated_mail.triggered.connect(
+ self._show_pixelated_browser)
self.ui.action_about_leap.triggered.connect(self._about)
self.ui.action_quit.triggered.connect(self.quit)
self.ui.action_wizard.triggered.connect(self._show_wizard)
@@ -568,6 +572,10 @@ class MainWindow(QtGui.QMainWindow, SignalTracker):
pref_win = PreferencesWindow(self, account, self.app)
pref_win.show()
+ def _show_pixelated_browser(self):
+ win = PixelatedWindow(self)
+ win.show()
+
def _update_eip_enabled_status(self, account=None, services=None):
"""
TRIGGER:
diff --git a/src/leap/bitmask/gui/qt_browser.py b/src/leap/bitmask/gui/qt_browser.py
new file mode 100644
index 00000000..4bd947cb
--- /dev/null
+++ b/src/leap/bitmask/gui/qt_browser.py
@@ -0,0 +1,13 @@
+from PySide import QtCore, QtWebKit, QtGui
+
+PIXELATED_URI = 'http://localhost:9090'
+
+
+class PixelatedWindow(QtGui.QDialog):
+
+ def __init__(self, parent):
+ QtGui.QDialog.__init__(self, parent)
+ self.web = QtWebKit.QWebView(self)
+ self.web.load(QtCore.QUrl(PIXELATED_URI))
+ self.setWindowTitle('Bitmask/Pixelated WebMail')
+ self.web.show()
diff --git a/src/leap/bitmask/gui/ui/mainwindow.ui b/src/leap/bitmask/gui/ui/mainwindow.ui
index b1d68c4a..976c0c0a 100644
--- a/src/leap/bitmask/gui/ui/mainwindow.ui
+++ b/src/leap/bitmask/gui/ui/mainwindow.ui
@@ -315,6 +315,7 @@
+
@@ -370,6 +371,11 @@
Create a new account...
+
+
+ Bitmask Webmail
+
+ false
--
cgit v1.2.3
From 106d202012f8f052a3cabe044d7287d2283655fc Mon Sep 17 00:00:00 2001
From: Kali Kaneko
Date: Thu, 24 Mar 2016 10:04:38 -0400
Subject: [feature] hide browser menu entry if pixelated is disabled
---
src/leap/bitmask/gui/mainwindow.py | 4 ++++
src/leap/bitmask/gui/qt_browser.py | 20 ++++++++++++++++++++
2 files changed, 24 insertions(+)
diff --git a/src/leap/bitmask/gui/mainwindow.py b/src/leap/bitmask/gui/mainwindow.py
index 1f497d2d..839aae87 100644
--- a/src/leap/bitmask/gui/mainwindow.py
+++ b/src/leap/bitmask/gui/mainwindow.py
@@ -222,6 +222,10 @@ class MainWindow(QtGui.QMainWindow, SignalTracker):
self.ui.action_preferences.triggered.connect(self._show_preferences)
self.ui.action_pixelated_mail.triggered.connect(
self._show_pixelated_browser)
+
+ pixelated_enabled = self._settings.get_pixelmail_enabled()
+ self.ui.action_pixelated_mail.setVisible(pixelated_enabled)
+
self.ui.action_about_leap.triggered.connect(self._about)
self.ui.action_quit.triggered.connect(self.quit)
self.ui.action_wizard.triggered.connect(self._show_wizard)
diff --git a/src/leap/bitmask/gui/qt_browser.py b/src/leap/bitmask/gui/qt_browser.py
index 4bd947cb..e480b363 100644
--- a/src/leap/bitmask/gui/qt_browser.py
+++ b/src/leap/bitmask/gui/qt_browser.py
@@ -1,3 +1,23 @@
+# -*- coding: utf-8 -*-
+# qt_browser.py
+# Copyright (C) 2016 LEAP
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see .
+"""
+QtWebKit-based browser to display Pixelated User Agent
+"""
+
from PySide import QtCore, QtWebKit, QtGui
PIXELATED_URI = 'http://localhost:9090'
--
cgit v1.2.3
From 8ab91a80f1c0ef4e49f682342e9479d140f55c9a Mon Sep 17 00:00:00 2001
From: Kali Kaneko
Date: Thu, 24 Mar 2016 10:50:53 -0400
Subject: [fix] get smtp config from smtp-provider.json
---
src/leap/bitmask/pix.py | 44 ++++++++++++++++++++++++++++++--------------
1 file changed, 30 insertions(+), 14 deletions(-)
diff --git a/src/leap/bitmask/pix.py b/src/leap/bitmask/pix.py
index abc8a822..96ca4299 100644
--- a/src/leap/bitmask/pix.py
+++ b/src/leap/bitmask/pix.py
@@ -17,11 +17,13 @@
"""
Pixelated plugin integration.
"""
+import json
import os
from twisted.internet import defer
from twisted.python import log
+from leap.bitmask.util import get_path_prefix
from leap.mail.imap.account import IMAPAccount
from pixelated.adapter.mailstore import LeapMailStore
@@ -37,13 +39,11 @@ from pixelated.resources.root_resource import RootResource
def start_pixelated_user_agent(userid, soledad, keymanager):
- print 'STARTING PIXELATED USER AGENT...'
-
leap_session = LeapSessionAdapter(
userid, soledad, keymanager)
config = Config()
- leap_home = os.path.expanduser('~/.config/leap')
+ leap_home = os.path.join(get_path_prefix(), 'leap')
config.leap_home = leap_home
leap_session.config = config
@@ -62,6 +62,20 @@ def start_pixelated_user_agent(userid, soledad, keymanager):
return deferred
+def get_smtp_config(provider):
+ config_path = os.path.join(
+ get_path_prefix(), 'leap', 'providers', provider, 'smtp-service.json')
+ json_config = json.loads(open(config_path).read())
+ chosen_host = json_config['hosts'].keys()[0]
+ hostname = json_config['hosts'][chosen_host]['hostname']
+ port = json_config['hosts'][chosen_host]['port']
+
+ config = Config()
+ config.host = hostname
+ config.port = port
+ return config
+
+
class LeapSessionAdapter(object):
def __init__(self, userid, soledad, keymanager):
@@ -69,6 +83,7 @@ class LeapSessionAdapter(object):
self.soledad = soledad
+ # FIXME this expects a keymanager-like instance
self.nicknym = Config()
self.nicknym.keymanager = keymanager
@@ -77,22 +92,23 @@ class LeapSessionAdapter(object):
self.user_auth = Config()
self.user_auth.uuid = soledad.uuid
- # XXX what is this?? path to smtp-service?
- # self.config = provider.config
- # self.provider = provider
-
self.fresh_account = False
self.incoming_mail_fetcher = None
self.account = IMAPAccount(userid, soledad, defer.Deferred())
username, provider = userid.split('@')
- smtp_client_cert = os.path.expanduser(
- '~/.config/leap/providers/{provider}/keys/'
- 'client/smtp_{username}.pem'.format(
- provider=provider, username=username))
- # TODO --- get from config
- smtp_host = 'antelope.mail.bitmask.net'
- smtp_port = 2013
+ smtp_client_cert = os.path.join(
+ get_path_prefix(),
+ 'leap', 'providers', provider, 'keys',
+ 'client',
+ 'smtp_{username}.pem'.format(
+ username=username))
+
+ assert(os.path.isfile(smtp_client_cert))
+
+ smtp_config = get_smtp_config(provider)
+ smtp_host = smtp_config.host
+ smtp_port = smtp_config.port
self.smtp_config = LeapSMTPConfig(
userid,
--
cgit v1.2.3
From ae5663769f2231f51b1cf2682bc6b6039dc0ab13 Mon Sep 17 00:00:00 2001
From: Kali Kaneko
Date: Thu, 24 Mar 2016 19:10:24 -0400
Subject: [feature] pass the path to pixelated_www package
---
src/leap/bitmask/pix.py | 14 ++++++++++++--
1 file changed, 12 insertions(+), 2 deletions(-)
diff --git a/src/leap/bitmask/pix.py b/src/leap/bitmask/pix.py
index 96ca4299..8242255c 100644
--- a/src/leap/bitmask/pix.py
+++ b/src/leap/bitmask/pix.py
@@ -19,6 +19,7 @@ Pixelated plugin integration.
"""
import json
import os
+import sys
from twisted.internet import defer
from twisted.python import log
@@ -26,6 +27,8 @@ from twisted.python import log
from leap.bitmask.util import get_path_prefix
from leap.mail.imap.account import IMAPAccount
+import pixelated_www
+
from pixelated.adapter.mailstore import LeapMailStore
from pixelated.adapter.welcome_mail import add_welcome_mail
from pixelated.application import SingleUserServicesFactory
@@ -49,12 +52,19 @@ def start_pixelated_user_agent(userid, soledad, keymanager):
services_factory = SingleUserServicesFactory(
UserAgentMode(is_single_user=True))
- resource = RootResource(services_factory)
+ if getattr(sys, 'frozen', False):
+ # we are running in a |PyInstaller| bundle
+ static_folder = os.path.join(sys._MEIPASS, 'pixelated_www')
+ else:
+ static_folder = os.path.abspath(pixelated_www.__path__)
+
+ resource = RootResource(services_factory, static_folder=static_folder)
+
+ config.host = 'localhost'
config.port = 9090
config.sslkey = None
config.sslcert = None
- config.host = 'localhost'
deferred = _start_in_single_user_mode(
leap_session, config,
--
cgit v1.2.3
From 68f11cff01c18750036afdd97ac9074f8538b676 Mon Sep 17 00:00:00 2001
From: Kali Kaneko
Date: Mon, 28 Mar 2016 12:22:08 -0400
Subject: [docs] readme for pixelated functionality
---
pkg/PixelatedWebmail.README | 38 ++++++++++++++++++++++++++++++++++++++
1 file changed, 38 insertions(+)
create mode 100644 pkg/PixelatedWebmail.README
diff --git a/pkg/PixelatedWebmail.README b/pkg/PixelatedWebmail.README
new file mode 100644
index 00000000..c45dc9ae
--- /dev/null
+++ b/pkg/PixelatedWebmail.README
@@ -0,0 +1,38 @@
+How to enable Pixelated Webmail
+-------------------------------
+
+WARNING! This is an experimental feature.
+It can expose your mail to *any* user with access to your machine, since there
+is no authentication in place at the moment. It could even eat your data. You
+have been warned.
+
+Ok, how do I enable this wonderful feature?
+-------------------------------------------
+
+First, run the bundle for a first time, and ensure that you can register a new
+account with a mail-enabled provider (for instance, mail.bitmask.net).
+
+Then, you have to edit a config file living inside the bundle folders. You have
+to add "Pixmail=true" under the [General] section, like this:
+
+config/leap/leap.conf:
+
+[General]
+SkipFirstRun=true
+Provider=mail.bitmask.net
+Pixmail=true
+
+[mail.bitmask.net]
+Services=mx
+
+Then, run bitmask again:
+
+./bitmask --debug
+
+And a new "Bitmask Webmail" option should have appeared under the "Bitmask"
+menu.
+
+If you want to disable the Webmail functionality, just set the Pixmail property
+to 'false'.
+
+Enjoy your local and encrypted pixelated webmail!
--
cgit v1.2.3
From 1699a0c9849de6581f1e2c5ee74ea8d3c83d3591 Mon Sep 17 00:00:00 2001
From: Kali Kaneko
Date: Mon, 28 Mar 2016 12:23:31 -0400
Subject: [pkg] some pyinstaller hacky targets
---
Makefile | 26 ++++++++++++++++++++++++++
1 file changed, 26 insertions(+)
diff --git a/Makefile b/Makefile
index 1cfeecb4..30e67962 100644
--- a/Makefile
+++ b/Makefile
@@ -167,6 +167,32 @@ sumo_tarball_latest: checkout_leapdeps_develop pull_leapdeps setup_without_names
pyinst:
pyinstaller -y pkg/pyinst/bitmask.spec
+pyinst-hacks:
+ cp ../leap_common/src/leap/common/cacert.pem dist/bitmask/
+ mkdir -p dist/bitmask/pysqlcipher
+ cp $(VIRTUAL_ENV)/lib/python2.7/site-packages/pysqlcipher/_sqlite.so dist/bitmask/pysqlcipher
+ cp -r $(VIRTUAL_ENV)/lib/python2.7/site-packages/pixelated_www dist/bitmask/
+
+pyinst-wrapper:
+ mv dist/bitmask/bitmask dist/bitmask/bitmask-app
+ cp pkg/linux/bitmask-launcher dist/bitmask/bitmask
+ cp pkg/PixelatedWebmail.README dist/bitmask
+
+pyinst-trim:
+ rm dist/bitmask/libQtOpenGL.so.4
+ rm dist/bitmask/libQtSql.so.4
+ rm dist/bitmask/libQt3Support.so.4
+ rm dist/bitmask/libnvidia-glcore.so.352.79
+ rm dist/bitmask/libgstvideo-1.0.so.0
+ rm dist/bitmask/libgstaudio-1.0.so.0
+ rm dist/bitmask/libgstreamer-1.0.so.0
+ rm dist/bitmask/libnvidia-tls.so.352.79
+ rm dist/bitmask/libaudio.so.2
+
+pyinst-dist:
+ rm -rf dist/bitmask/config
+ cd dist/ && tar cvzf Bitmask.0.9.2.alpha1.tar.gz bitmask
+
clean_pkg:
rm -rf build dist
--
cgit v1.2.3
From b7a435abc0f0c366fdc91f6be240b76e8332e4c6 Mon Sep 17 00:00:00 2001
From: Kali Kaneko
Date: Mon, 28 Mar 2016 12:23:59 -0400
Subject: [pkg] pass --standalone flag to binary
---
pkg/linux/bitmask-launcher | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/pkg/linux/bitmask-launcher b/pkg/linux/bitmask-launcher
index 550dd134..90ced511 100755
--- a/pkg/linux/bitmask-launcher
+++ b/pkg/linux/bitmask-launcher
@@ -6,4 +6,4 @@
[ -f libQtGui.so.4 ] || ln -s libQtGui.so.4.orig libQtGui.so.4
cat /etc/os-release | grep ID | grep -i ubuntu && unlink libQtCore.so.4 && unlink libQtGui.so.4
-./bitmask-app "$@"
+./bitmask-app --standalone "$@"
--
cgit v1.2.3
From 7133000f82b79470fa91c42b286fffeeece28631 Mon Sep 17 00:00:00 2001
From: Kali Kaneko
Date: Mon, 28 Mar 2016 12:24:48 -0400
Subject: [pkg] update versions for bundle
---
pkg/pyinst/bitmask.spec | 9 +++++----
1 file changed, 5 insertions(+), 4 deletions(-)
diff --git a/pkg/pyinst/bitmask.spec b/pkg/pyinst/bitmask.spec
index 2bc2f9d2..a76ccb17 100644
--- a/pkg/pyinst/bitmask.spec
+++ b/pkg/pyinst/bitmask.spec
@@ -1,12 +1,13 @@
# -*- mode: python -*-
+import sys
block_cipher = None
-a = Analysis([os.path.join('pkg', 'pyinst', 'bitmask.py')],
+a = Analysis([os.path.join('bitmask.py')],
hiddenimports=[
'zope.interface', 'zope.proxy',
- 'PySide.QtCore', 'PySide.QtGui'],
+ 'PySide.QtCore', 'PySide.QtGui', 'PySide.QtWebKit'],
hookspath=None,
runtime_hooks=None,
excludes=None,
@@ -33,6 +34,6 @@ if sys.platform.startswith("darwin"):
name=os.path.join(
'dist', 'Bitmask.app'),
appname='Bitmask',
- version='0.9.0rc2',
+ version='0.9.2alpha1',
icon='pkg/osx/bitmask.icns',
- bundle_identifier='bitmask-0.9.0rc2')
+ bundle_identifier='bitmask-0.9.2alpha1')
--
cgit v1.2.3
From 054ceb6225ef9c32f3d24870bf3e8085bbe0c432 Mon Sep 17 00:00:00 2001
From: Kali Kaneko
Date: Mon, 28 Mar 2016 12:25:29 -0400
Subject: [pkg] update freeze_deb command
---
setup.py | 9 +++++----
1 file changed, 5 insertions(+), 4 deletions(-)
diff --git a/setup.py b/setup.py
index fc9c36c9..15327bf1 100755
--- a/setup.py
+++ b/setup.py
@@ -105,13 +105,13 @@ class freeze_debianver(Command):
# of this file.
version_version = '{version}'
-version_revisionid = '{version_revision}'
+full_revisionid = '{full_revisionid}'
"""
templatefun = r"""
def get_versions(default={}, verbose=False):
return {'version': version_version,
- 'full-revisionid': version_revisionid}
+ 'full-revisionid': full_revisionid}
"""
def initialize_options(self):
@@ -128,8 +128,9 @@ def get_versions(default={}, verbose=False):
return
subst_template = self.template.format(
version=VERSION_SHORT,
- version_full=VERSION_REVISION) + self.templatefun
- with open(versioneer.versionfile_source, 'w') as f:
+ full_revisionid=VERSION_REVISION) + self.templatefun
+ versioneer_cfg = versioneer.get_config_from_root('.')
+ with open(versioneer_cfg.versionfile_source, 'w') as f:
f.write(subst_template)
--
cgit v1.2.3
From 098b0974925c44dad1e98352670959cba66f9c0a Mon Sep 17 00:00:00 2001
From: Kali Kaneko
Date: Mon, 28 Mar 2016 12:27:13 -0400
Subject: [bug] fix case for constant
---
src/leap/bitmask/config/leapsettings.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/leap/bitmask/config/leapsettings.py b/src/leap/bitmask/config/leapsettings.py
index a060c8a4..d7590c24 100644
--- a/src/leap/bitmask/config/leapsettings.py
+++ b/src/leap/bitmask/config/leapsettings.py
@@ -353,7 +353,7 @@ class LeapSettings(object):
:type skip: bool
"""
leap_assert_type(skip, bool)
- self._settings.setvalue(self.skipfirstrun_key, skip)
+ self._settings.setValue(self.SKIPFIRSTRUN_KEY, skip)
def get_pixelmail_enabled(self):
return to_bool(self._settings.value(self.PIXELMAIL_KEY, False))
--
cgit v1.2.3
From 541cf77d2c7bc9202474cce4c10b535a9c225ccd Mon Sep 17 00:00:00 2001
From: Kali Kaneko
Date: Mon, 28 Mar 2016 12:28:52 -0400
Subject: [bug] set standalone flag properly
otherwise, the configs are saved to the user home config folder.
---
src/leap/bitmask/services/__init__.py | 3 +++
1 file changed, 3 insertions(+)
diff --git a/src/leap/bitmask/services/__init__.py b/src/leap/bitmask/services/__init__.py
index 54426669..d86f8aa4 100644
--- a/src/leap/bitmask/services/__init__.py
+++ b/src/leap/bitmask/services/__init__.py
@@ -154,6 +154,9 @@ def download_service_config(provider_config, service_config,
# Not modified
service_path = ("leap", "providers", provider_config.get_domain(),
service_json)
+
+ service_config.__class__.standalone = flags.STANDALONE
+
if res.status_code == 304:
logger.debug(
"{0} definition has not been modified".format(
--
cgit v1.2.3
From 62e9ae1bc0e28961e10b46646f6131152844d94c Mon Sep 17 00:00:00 2001
From: Kali Kaneko
Date: Mon, 28 Mar 2016 12:29:57 -0400
Subject: [bug] instantiate soledadconfig if needed
---
src/leap/bitmask/services/soledad/soledadbootstrapper.py | 3 +++
1 file changed, 3 insertions(+)
diff --git a/src/leap/bitmask/services/soledad/soledadbootstrapper.py b/src/leap/bitmask/services/soledad/soledadbootstrapper.py
index a10a2731..21cdee31 100644
--- a/src/leap/bitmask/services/soledad/soledadbootstrapper.py
+++ b/src/leap/bitmask/services/soledad/soledadbootstrapper.py
@@ -331,6 +331,9 @@ class SoledadBootstrapper(AbstractBootstrapper):
:returns: the server url
:rtype: unicode
"""
+ if not self._soledad_config:
+ self._soledad_config = SoledadConfig()
+
# TODO: Select server based on timezone (issue #3308)
server_dict = self._soledad_config.get_hosts()
--
cgit v1.2.3
From aefc5edec1d6bd693bae72235ab58312e49bb236 Mon Sep 17 00:00:00 2001
From: Kali Kaneko
Date: Tue, 29 Mar 2016 12:58:14 -0400
Subject: [doc] add entry in next-changelog for the pixelated feature
---
changes/next-changelog.rst | 1 +
1 file changed, 1 insertion(+)
diff --git a/changes/next-changelog.rst b/changes/next-changelog.rst
index d07273ec..b20efdc8 100644
--- a/changes/next-changelog.rst
+++ b/changes/next-changelog.rst
@@ -14,6 +14,7 @@ Features
- `#7656 `_: Adapt to multi-user aware events.
- `#4469 `_: Display randomly generated service token on the Help Window.
- Use cred-based authentication on SMTP.
+- Experimental support for the Pixelated WebMail.
- `#1234 `_: Description of the new feature corresponding with issue #1234.
- New feature without related issue number.
--
cgit v1.2.3
From ea9a9f09c33f4f5e6faf0a8297200f44688eb86f Mon Sep 17 00:00:00 2001
From: Kali Kaneko
Date: Wed, 30 Mar 2016 12:22:35 -0400
Subject: [pkg] add requirements file for pixelated user agent
---
pkg/requirements-pixelated.pip | 4 ++++
1 file changed, 4 insertions(+)
create mode 100644 pkg/requirements-pixelated.pip
diff --git a/pkg/requirements-pixelated.pip b/pkg/requirements-pixelated.pip
new file mode 100644
index 00000000..d1f8004d
--- /dev/null
+++ b/pkg/requirements-pixelated.pip
@@ -0,0 +1,4 @@
+--find-links https://downloads.leap.se/libs/pixelated/
+pixelated-user-agent
+pixelated-www
+whoosh
--
cgit v1.2.3
From 746d76c8e6f02ba417b7fb9d47630c4e83b40126 Mon Sep 17 00:00:00 2001
From: Kali Kaneko
Date: Thu, 31 Mar 2016 10:38:11 -0400
Subject: [bug] workaround for incompatible qt library in ubuntu
- Resolves: #7990
---
Makefile | 49 ++++++++++++++++++++++++++++------------------
pkg/linux/bitmask-launcher | 15 +++++++++++++-
2 files changed, 44 insertions(+), 20 deletions(-)
diff --git a/Makefile b/Makefile
index 30e67962..c3f0e0d2 100644
--- a/Makefile
+++ b/Makefile
@@ -40,6 +40,9 @@ PYRCC = pyside-rcc
PYLUP = pyside-lupdate
LRELE = lrelease
+# pyinst dist dir
+DIST = dist/bitmask/
+
#################################
# DO NOT EDIT FOLLOWING
@@ -165,33 +168,41 @@ sumo_tarball_latest: checkout_leapdeps_develop pull_leapdeps setup_without_names
git checkout -- setup.py
pyinst:
+ echo "MAKE SURE OF FREEZING VERSION FIRST!"
pyinstaller -y pkg/pyinst/bitmask.spec
pyinst-hacks:
- cp ../leap_common/src/leap/common/cacert.pem dist/bitmask/
- mkdir -p dist/bitmask/pysqlcipher
- cp $(VIRTUAL_ENV)/lib/python2.7/site-packages/pysqlcipher/_sqlite.so dist/bitmask/pysqlcipher
- cp -r $(VIRTUAL_ENV)/lib/python2.7/site-packages/pixelated_www dist/bitmask/
+ cp ../leap_common/src/leap/common/cacert.pem $(DIST)
+ mkdir -p $(DIST)pysqlcipher
+ cp $(VIRTUAL_ENV)/lib/python2.7/site-packages/pysqlcipher/_sqlite.so $(DIST)pysqlcipher
+ cp -r $(VIRTUAL_ENV)/lib/python2.7/site-packages/pixelated_www $(DIST)
+
+pyinst-trim:
+ rm -f $(DIST)libQtOpenGL.so.4
+ rm -f $(DIST)libQtSql.so.4
+ rm -f $(DIST)libQt3Support.so.4
+ rm -f $(DIST)libaudio.so.2
+ rm -f $(DIST)libnvidia-*
+ #rm -f dist/bitmask/libgstvideo-1.0.so.0
+ #rm -f dist/bitmask/libgstaudio0.0.so.0
+ #rm -f dist/bitmask/libgstreamer-1.0.so.0
pyinst-wrapper:
- mv dist/bitmask/bitmask dist/bitmask/bitmask-app
- cp pkg/linux/bitmask-launcher dist/bitmask/bitmask
- cp pkg/PixelatedWebmail.README dist/bitmask
+ mv $(DIST)libQtCore.so.4 $(DIST)libQtCore.so.4.orig
+ mv $(DIST)libQtGui.so.4 $(DIST)libQtGui.so.4.orig
+ mv $(DIST)libQtNetwork.so.4 $(DIST)libQtNetwork.so.4.orig
+ mv $(DIST)libQtSvg.so.4 $(DIST)libQtSvg.so.4.orig
+ mv $(DIST)libQtWebKit.so.4 $(DIST)libQtWebKit.so.4.orig
+ mv $(DIST)libQtXmlPatterns.so.4 $(DIST)libQtXmlPatterns.so.4.orig
+ mv $(DIST)libQtXml.so.4 $(DIST)libQtXml.so.4.orig
+ mv $(DIST)bitmask $(DIST)bitmask-app
+ cp pkg/linux/bitmask-launcher $(DIST)bitmask
+ cp pkg/PixelatedWebmail.README $(DIST)
-pyinst-trim:
- rm dist/bitmask/libQtOpenGL.so.4
- rm dist/bitmask/libQtSql.so.4
- rm dist/bitmask/libQt3Support.so.4
- rm dist/bitmask/libnvidia-glcore.so.352.79
- rm dist/bitmask/libgstvideo-1.0.so.0
- rm dist/bitmask/libgstaudio-1.0.so.0
- rm dist/bitmask/libgstreamer-1.0.so.0
- rm dist/bitmask/libnvidia-tls.so.352.79
- rm dist/bitmask/libaudio.so.2
pyinst-dist:
- rm -rf dist/bitmask/config
- cd dist/ && tar cvzf Bitmask.0.9.2.alpha1.tar.gz bitmask
+ rm -rf $(DIST)config
+ cd dist/ && tar cvzf Bitmask.0.9.2.alpha2.tar.gz bitmask
clean_pkg:
rm -rf build dist
diff --git a/pkg/linux/bitmask-launcher b/pkg/linux/bitmask-launcher
index 90ced511..3eae57c0 100755
--- a/pkg/linux/bitmask-launcher
+++ b/pkg/linux/bitmask-launcher
@@ -4,6 +4,19 @@
[ -f libQtCore.so.4 ] || ln -s libQtCore.so.4.orig libQtCore.so.4
[ -f libQtGui.so.4 ] || ln -s libQtGui.so.4.orig libQtGui.so.4
-cat /etc/os-release | grep ID | grep -i ubuntu && unlink libQtCore.so.4 && unlink libQtGui.so.4
+[ -f libQtNetwork.so.4 ] || ln -s libQtNetwork.so.4.orig libQtNetwork.so.4
+[ -f libQtSvg.so.4 ] || ln -s libQtSvg.so.4.orig libQtSvg.so.4
+[ -f libQtWebKit.so.4 ] || ln -s libQtWebKit.so.4.orig libQtWebKit.so.4
+[ -f libQtXmlPatterns.so.4 ] || ln -s libQtXmlPatterns.so.4.orig libQtXmlPatterns.so.4
+[ -f libQtXml.so.4 ] || ln -s libQtXml.so.4.orig libQtXml.so.4
+
+cat /etc/os-release | grep ID | grep -i ubuntu && \
+ unlink libQtCore.so.4 && \
+ unlink libQtGui.so.4 && \
+ unlink libQtNetwork.so.4 && \
+ unlink libQtSvg.so.4 && \
+ unlink libQtWebKit.so.4 && \
+ unlink libQtXmlPatterns.so.4 && \
+ unlink libQtXml.so.4
./bitmask-app --standalone "$@"
--
cgit v1.2.3
From eb55be39cea024b253ee784dc304e72f1af94d7f Mon Sep 17 00:00:00 2001
From: Elijah Sparrow
Date: Wed, 13 Jan 2016 15:27:47 -0800
Subject: update docker readme
fix docker readme to reflect the proper commands
---
docker/README.rst | 8 +++-----
1 file changed, 3 insertions(+), 5 deletions(-)
diff --git a/docker/README.rst b/docker/README.rst
index 70d44809..4a2d08e7 100644
--- a/docker/README.rst
+++ b/docker/README.rst
@@ -6,11 +6,9 @@ Here we have several tools that leverages docker to ease Bitmask testing.
``bitmask-docker.sh`` is a helper script to ``build`` and ``run`` the bitmask app,
here is an example usage::
- $ ./bitmask-docker build # build docker image
- $ ./bitmask-docker init ro bitmask-nightly.json # initialize all the stuff needed
- # ....
- $ ./bitmask-docker.sh run
-
+ $ ./bitmask-docker.sh build # build docker image
+ $ ./bitmask-docker.sh init bitmask-nightly.json # initialize (takes time)
+ $ ./bitmask-docker.sh run # run bitmask in docker
``bitmask-nightly.json`` is the version specifier for each bitmask component that
will be used to run bitmask.
--
cgit v1.2.3
From 9835bc05eaa0525df91a317c84f86b517ed57c73 Mon Sep 17 00:00:00 2001
From: Kali Kaneko
Date: Mon, 4 Apr 2016 10:16:52 -0400
Subject: [bug] update bootstrap script so that it installs pixelated reqs too
---
pkg/scripts/bootstrap_develop.sh | 1 +
1 file changed, 1 insertion(+)
diff --git a/pkg/scripts/bootstrap_develop.sh b/pkg/scripts/bootstrap_develop.sh
index 68edcd43..3695fabc 100755
--- a/pkg/scripts/bootstrap_develop.sh
+++ b/pkg/scripts/bootstrap_develop.sh
@@ -118,6 +118,7 @@ setup_develop() {
# hack to solve gnupg version problem
pip uninstall -y gnupg && pip install gnupg
+ pip install -r pkg/requirements-pixelated.pip
set +x
echo "${cc_green}Status: $status done.${cc_normal}"
}
--
cgit v1.2.3
From fe96e2eef29a538b856f0d8b4bbf3940e42364c1 Mon Sep 17 00:00:00 2001
From: Kali Kaneko
Date: Fri, 1 Apr 2016 12:55:00 -0400
Subject: [pkg] update to versioneer 0.16
---
setup.py | 11 +-
src/leap/bitmask/_version.py | 100 ++++++++++-------
versioneer.py | 261 ++++++++++++++++++++++++++++---------------
3 files changed, 233 insertions(+), 139 deletions(-)
diff --git a/setup.py b/setup.py
index 15327bf1..5bf5d186 100755
--- a/setup.py
+++ b/setup.py
@@ -26,6 +26,7 @@ import os
import re
from distutils.command.build import build as _build
+from setuptools import Command
if not sys.version_info[0] == 2:
print("[ERROR] Sorry, Python 3 is not supported (yet). "
@@ -84,11 +85,6 @@ if len(_version_short) > 0:
VERSION_SHORT = _version_short[0]
DOWNLOAD_URL = DOWNLOAD_BASE % VERSION_SHORT
-cmdclass = versioneer.get_cmdclass()
-
-
-from setuptools import Command
-
class freeze_debianver(Command):
@@ -99,7 +95,7 @@ class freeze_debianver(Command):
user_options = []
template = r"""
# This file was generated by the `freeze_debianver` command in setup.py
-# Using 'versioneer.py' (0.7+) from
+# Using 'versioneer.py' (0.16) from
# revision-control system data, or from the parent directory name of an
# unpacked source archive. Distribution tarballs contain a pre-generated copy
# of this file.
@@ -145,12 +141,12 @@ def freeze_pkg_ver(path, version_short, version_full):
with open(path, 'w') as f:
f.write(subst_template)
-
if sys.argv[:1] == '--sumo':
IS_SUMO = True
else:
IS_SUMO = False
+cmdclass = versioneer.get_cmdclass()
cmdclass["freeze_debianver"] = freeze_debianver
parsed_reqs = utils.parse_requirements()
@@ -263,7 +259,6 @@ cmdclass["hash_binaries"] = cmd_binary_hash
# sdist class need to augment the versioneer modified ones
-#_build = cmdclass['build_py']
versioneer_sdist = cmdclass['sdist']
diff --git a/src/leap/bitmask/_version.py b/src/leap/bitmask/_version.py
index 8c507c92..f032a17a 100644
--- a/src/leap/bitmask/_version.py
+++ b/src/leap/bitmask/_version.py
@@ -6,7 +6,9 @@
# that just contains the computed version number.
# This file is released into the public domain. Generated by
-# versioneer-0.15 (https://github.com/warner/python-versioneer)
+# versioneer-0.16 (https://github.com/warner/python-versioneer)
+
+"""Git implementation of _version.py."""
import errno
import os
@@ -16,6 +18,7 @@ import sys
def get_keywords():
+ """Get the keywords needed to look up the version information."""
# these strings will be replaced by git during git-archive.
# setup.py/versioneer.py will grep for the variable names, so they must
# each be defined on a line of their own. _version.py will just call
@@ -27,10 +30,11 @@ def get_keywords():
class VersioneerConfig:
- pass
+ """Container for Versioneer configuration parameters."""
def get_config():
+ """Create, populate and return the VersioneerConfig() object."""
# these strings are filled in when 'setup.py versioneer' creates
# _version.py
cfg = VersioneerConfig()
@@ -44,7 +48,7 @@ def get_config():
class NotThisMethod(Exception):
- pass
+ """Exception raised if a method is not valid for the current scenario."""
LONG_VERSION_PY = {}
@@ -52,7 +56,9 @@ HANDLERS = {}
def register_vcs_handler(vcs, method): # decorator
+ """Decorator to mark a method as the handler for a particular VCS."""
def decorate(f):
+ """Store f in HANDLERS[vcs][method]."""
if vcs not in HANDLERS:
HANDLERS[vcs] = {}
HANDLERS[vcs][method] = f
@@ -61,6 +67,7 @@ def register_vcs_handler(vcs, method): # decorator
def run_command(commands, args, cwd=None, verbose=False, hide_stderr=False):
+ """Call the given command(s)."""
assert isinstance(commands, list)
p = None
for c in commands:
@@ -94,8 +101,11 @@ def run_command(commands, args, cwd=None, verbose=False, hide_stderr=False):
def versions_from_parentdir(parentdir_prefix, root, verbose):
- # Source tarballs conventionally unpack into a directory that includes
- # both the project name and a version string.
+ """Try to determine the version from the parent directory name.
+
+ Source tarballs conventionally unpack into a directory that includes
+ both the project name and a version string.
+ """
dirname = os.path.basename(root)
if not dirname.startswith(parentdir_prefix):
if verbose:
@@ -109,6 +119,7 @@ def versions_from_parentdir(parentdir_prefix, root, verbose):
@register_vcs_handler("git", "get_keywords")
def git_get_keywords(versionfile_abs):
+ """Extract version information from the given file."""
# the code embedded in _version.py can just fetch the value of these
# keywords. When used from setup.py, we don't want to import _version.py,
# so we do it with a regexp instead. This function is not used from
@@ -133,6 +144,7 @@ def git_get_keywords(versionfile_abs):
@register_vcs_handler("git", "keywords")
def git_versions_from_keywords(keywords, tag_prefix, verbose):
+ """Get version information from git keywords."""
if not keywords:
raise NotThisMethod("no keywords at all, weird")
refnames = keywords["refnames"].strip()
@@ -178,11 +190,12 @@ def git_versions_from_keywords(keywords, tag_prefix, verbose):
@register_vcs_handler("git", "pieces_from_vcs")
def git_pieces_from_vcs(tag_prefix, root, verbose, run_command=run_command):
- # this runs 'git' from the root of the source tree. This only gets called
- # if the git-archive 'subst' keywords were *not* expanded, and
- # _version.py hasn't already been rewritten with a short version string,
- # meaning we're inside a checked out source tree.
+ """Get version from 'git describe' in the root of the source tree.
+ This only gets called if the git-archive 'subst' keywords were *not*
+ expanded, and _version.py hasn't already been rewritten with a short
+ version string, meaning we're inside a checked out source tree.
+ """
if not os.path.exists(os.path.join(root, ".git")):
if verbose:
print("no .git in %s" % root)
@@ -191,10 +204,11 @@ def git_pieces_from_vcs(tag_prefix, root, verbose, run_command=run_command):
GITS = ["git"]
if sys.platform == "win32":
GITS = ["git.cmd", "git.exe"]
- # if there is a tag, this yields TAG-NUM-gHEX[-dirty]
- # if there are no tags, this yields HEX[-dirty] (no NUM)
+ # if there is a tag matching tag_prefix, this yields TAG-NUM-gHEX[-dirty]
+ # if there isn't one, this yields HEX[-dirty] (no NUM)
describe_out = run_command(GITS, ["describe", "--tags", "--dirty",
- "--always", "--long"],
+ "--always", "--long",
+ "--match", "%s*" % tag_prefix],
cwd=root)
# --long was added in git-1.5.5
if describe_out is None:
@@ -259,19 +273,21 @@ def git_pieces_from_vcs(tag_prefix, root, verbose, run_command=run_command):
def plus_or_dot(pieces):
+ """Return a + if we don't already have one, else return a ."""
if "+" in pieces.get("closest-tag", ""):
return "."
return "+"
def render_pep440(pieces):
- # now build up version string, with post-release "local version
- # identifier". Our goal: TAG[+DISTANCE.gHEX[.dirty]] . Note that if you
- # get a tagged build and then dirty it, you'll get TAG+0.gHEX.dirty
+ """Build up version string, with post-release "local version identifier".
- # exceptions:
- # 1: no tags. git_describe was just HEX. 0+untagged.DISTANCE.gHEX[.dirty]
+ Our goal: TAG[+DISTANCE.gHEX[.dirty]] . Note that if you
+ get a tagged build and then dirty it, you'll get TAG+0.gHEX.dirty
+ Exceptions:
+ 1: no tags. git_describe was just HEX. 0+untagged.DISTANCE.gHEX[.dirty]
+ """
if pieces["closest-tag"]:
rendered = pieces["closest-tag"]
if pieces["distance"] or pieces["dirty"]:
@@ -289,11 +305,11 @@ def render_pep440(pieces):
def render_pep440_pre(pieces):
- # TAG[.post.devDISTANCE] . No -dirty
-
- # exceptions:
- # 1: no tags. 0.post.devDISTANCE
+ """TAG[.post.devDISTANCE] -- No -dirty.
+ Exceptions:
+ 1: no tags. 0.post.devDISTANCE
+ """
if pieces["closest-tag"]:
rendered = pieces["closest-tag"]
if pieces["distance"]:
@@ -305,14 +321,15 @@ def render_pep440_pre(pieces):
def render_pep440_post(pieces):
- # TAG[.postDISTANCE[.dev0]+gHEX] . The ".dev0" means dirty. Note that
- # .dev0 sorts backwards (a dirty tree will appear "older" than the
- # corresponding clean one), but you shouldn't be releasing software with
- # -dirty anyways.
+ """TAG[.postDISTANCE[.dev0]+gHEX] .
- # exceptions:
- # 1: no tags. 0.postDISTANCE[.dev0]
+ The ".dev0" means dirty. Note that .dev0 sorts backwards
+ (a dirty tree will appear "older" than the corresponding clean one),
+ but you shouldn't be releasing software with -dirty anyways.
+ Exceptions:
+ 1: no tags. 0.postDISTANCE[.dev0]
+ """
if pieces["closest-tag"]:
rendered = pieces["closest-tag"]
if pieces["distance"] or pieces["dirty"]:
@@ -331,11 +348,13 @@ def render_pep440_post(pieces):
def render_pep440_old(pieces):
- # TAG[.postDISTANCE[.dev0]] . The ".dev0" means dirty.
+ """TAG[.postDISTANCE[.dev0]] .
- # exceptions:
- # 1: no tags. 0.postDISTANCE[.dev0]
+ The ".dev0" means dirty.
+ Eexceptions:
+ 1: no tags. 0.postDISTANCE[.dev0]
+ """
if pieces["closest-tag"]:
rendered = pieces["closest-tag"]
if pieces["distance"] or pieces["dirty"]:
@@ -351,12 +370,13 @@ def render_pep440_old(pieces):
def render_git_describe(pieces):
- # TAG[-DISTANCE-gHEX][-dirty], like 'git describe --tags --dirty
- # --always'
+ """TAG[-DISTANCE-gHEX][-dirty].
- # exceptions:
- # 1: no tags. HEX[-dirty] (note: no 'g' prefix)
+ Like 'git describe --tags --dirty --always'.
+ Exceptions:
+ 1: no tags. HEX[-dirty] (note: no 'g' prefix)
+ """
if pieces["closest-tag"]:
rendered = pieces["closest-tag"]
if pieces["distance"]:
@@ -370,12 +390,14 @@ def render_git_describe(pieces):
def render_git_describe_long(pieces):
- # TAG-DISTANCE-gHEX[-dirty], like 'git describe --tags --dirty
- # --always -long'. The distance/hash is unconditional.
+ """TAG-DISTANCE-gHEX[-dirty].
- # exceptions:
- # 1: no tags. HEX[-dirty] (note: no 'g' prefix)
+ Like 'git describe --tags --dirty --always -long'.
+ The distance/hash is unconditional.
+ Exceptions:
+ 1: no tags. HEX[-dirty] (note: no 'g' prefix)
+ """
if pieces["closest-tag"]:
rendered = pieces["closest-tag"]
rendered += "-%d-g%s" % (pieces["distance"], pieces["short"])
@@ -388,6 +410,7 @@ def render_git_describe_long(pieces):
def render(pieces, style):
+ """Render the given version pieces into the requested style."""
if pieces["error"]:
return {"version": "unknown",
"full-revisionid": pieces.get("long"),
@@ -417,6 +440,7 @@ def render(pieces, style):
def get_versions():
+ """Get version information or return default if unable to do so."""
# I am in _version.py, which lives at ROOT/VERSIONFILE_SOURCE. If we have
# __file__, we can work backwards from there to the root. Some
# py2exe/bbfreeze/non-CPython implementations don't do __file__, in which
diff --git a/versioneer.py b/versioneer.py
index 89194938..24a69025 100644
--- a/versioneer.py
+++ b/versioneer.py
@@ -1,7 +1,8 @@
-# Version: 0.15
+# Version: 0.16
+
+"""The Versioneer - like a rocketeer, but for versions.
-"""
The Versioneer
==============
@@ -9,7 +10,7 @@ The Versioneer
* https://github.com/warner/python-versioneer
* Brian Warner
* License: Public Domain
-* Compatible With: python2.6, 2.7, 3.2, 3.3, 3.4, and pypy
+* Compatible With: python2.6, 2.7, 3.3, 3.4, 3.5, and pypy
* [![Latest Version]
(https://pypip.in/version/versioneer/badge.svg?style=flat)
](https://pypi.python.org/pypi/versioneer/)
@@ -125,16 +126,18 @@ First, decide on values for the following configuration variables:
If this is set to None, then `setup.py build` will not attempt to rewrite
any `_version.py` in the built tree. If your project does not have any
libraries (e.g. if it only builds a script), then you should use
- `versionfile_build = None` and override `distutils.command.build_scripts`
- to explicitly insert a copy of `versioneer.get_version()` into your
- generated script.
+ `versionfile_build = None`. To actually use the computed version string,
+ your `setup.py` will need to override `distutils.command.build_scripts`
+ with a subclass that explicitly inserts a copy of
+ `versioneer.get_version()` into your script file. See
+ `test/demoapp-script-only/setup.py` for an example.
* `tag_prefix`:
a string, like 'PROJECTNAME-', which appears at the start of all VCS tags.
If your tags look like 'myproject-1.2.0', then you should use
tag_prefix='myproject-'. If you use unprefixed tags like '1.2.0', this
- should be an empty string.
+ should be an empty string, using either `tag_prefix=` or `tag_prefix=''`.
* `parentdir_prefix`:
@@ -159,7 +162,7 @@ To versioneer-enable your project:
style = pep440
versionfile_source = src/myproject/_version.py
versionfile_build = myproject/_version.py
- tag_prefix = ""
+ tag_prefix =
parentdir_prefix = myproject-
````
@@ -286,6 +289,10 @@ To upgrade your project to a new release of Versioneer, do the following:
`SRC/_version.py`
* commit any changed files
+### Upgrading to 0.16
+
+Nothing special.
+
### Upgrading to 0.15
Starting with this version, Versioneer is configured with a `[versioneer]`
@@ -333,9 +340,11 @@ number of intermediate scripts.
## License
-To make Versioneer easier to embed, all its code is hereby released into the
-public domain. The `_version.py` that it creates is also in the public
-domain.
+To make Versioneer easier to embed, all its code is dedicated to the public
+domain. The `_version.py` that it creates is also in the public domain.
+Specifically, both are released under the Creative Commons "Public Domain
+Dedication" license (CC0-1.0), as described in
+https://creativecommons.org/publicdomain/zero/1.0/ .
"""
@@ -353,12 +362,15 @@ import sys
class VersioneerConfig:
- pass
+ """Container for Versioneer configuration parameters."""
def get_root():
- # we require that all commands are run from the project root, i.e. the
- # directory that contains setup.py, setup.cfg, and versioneer.py .
+ """Get the project root directory.
+
+ We require that all commands are run from the project root, i.e. the
+ directory that contains setup.py, setup.cfg, and versioneer.py .
+ """
root = os.path.realpath(os.path.abspath(os.getcwd()))
setup_py = os.path.join(root, "setup.py")
versioneer_py = os.path.join(root, "versioneer.py")
@@ -391,6 +403,7 @@ def get_root():
def get_config_from_root(root):
+ """Read the project setup.cfg file to determine Versioneer config."""
# This might raise EnvironmentError (if setup.cfg is missing), or
# configparser.NoSectionError (if it lacks a [versioneer] section), or
# configparser.NoOptionError (if it lacks "VCS="). See the docstring at
@@ -411,13 +424,15 @@ def get_config_from_root(root):
cfg.versionfile_source = get(parser, "versionfile_source")
cfg.versionfile_build = get(parser, "versionfile_build")
cfg.tag_prefix = get(parser, "tag_prefix")
+ if cfg.tag_prefix in ("''", '""'):
+ cfg.tag_prefix = ""
cfg.parentdir_prefix = get(parser, "parentdir_prefix")
cfg.verbose = get(parser, "verbose")
return cfg
class NotThisMethod(Exception):
- pass
+ """Exception raised if a method is not valid for the current scenario."""
# these dictionaries contain VCS-specific tools
LONG_VERSION_PY = {}
@@ -425,7 +440,9 @@ HANDLERS = {}
def register_vcs_handler(vcs, method): # decorator
+ """Decorator to mark a method as the handler for a particular VCS."""
def decorate(f):
+ """Store f in HANDLERS[vcs][method]."""
if vcs not in HANDLERS:
HANDLERS[vcs] = {}
HANDLERS[vcs][method] = f
@@ -434,6 +451,7 @@ def register_vcs_handler(vcs, method): # decorator
def run_command(commands, args, cwd=None, verbose=False, hide_stderr=False):
+ """Call the given command(s)."""
assert isinstance(commands, list)
p = None
for c in commands:
@@ -472,7 +490,9 @@ LONG_VERSION_PY['git'] = '''
# that just contains the computed version number.
# This file is released into the public domain. Generated by
-# versioneer-0.15 (https://github.com/warner/python-versioneer)
+# versioneer-0.16 (https://github.com/warner/python-versioneer)
+
+"""Git implementation of _version.py."""
import errno
import os
@@ -482,6 +502,7 @@ import sys
def get_keywords():
+ """Get the keywords needed to look up the version information."""
# these strings will be replaced by git during git-archive.
# setup.py/versioneer.py will grep for the variable names, so they must
# each be defined on a line of their own. _version.py will just call
@@ -493,10 +514,11 @@ def get_keywords():
class VersioneerConfig:
- pass
+ """Container for Versioneer configuration parameters."""
def get_config():
+ """Create, populate and return the VersioneerConfig() object."""
# these strings are filled in when 'setup.py versioneer' creates
# _version.py
cfg = VersioneerConfig()
@@ -510,7 +532,7 @@ def get_config():
class NotThisMethod(Exception):
- pass
+ """Exception raised if a method is not valid for the current scenario."""
LONG_VERSION_PY = {}
@@ -518,7 +540,9 @@ HANDLERS = {}
def register_vcs_handler(vcs, method): # decorator
+ """Decorator to mark a method as the handler for a particular VCS."""
def decorate(f):
+ """Store f in HANDLERS[vcs][method]."""
if vcs not in HANDLERS:
HANDLERS[vcs] = {}
HANDLERS[vcs][method] = f
@@ -527,6 +551,7 @@ def register_vcs_handler(vcs, method): # decorator
def run_command(commands, args, cwd=None, verbose=False, hide_stderr=False):
+ """Call the given command(s)."""
assert isinstance(commands, list)
p = None
for c in commands:
@@ -560,8 +585,11 @@ def run_command(commands, args, cwd=None, verbose=False, hide_stderr=False):
def versions_from_parentdir(parentdir_prefix, root, verbose):
- # Source tarballs conventionally unpack into a directory that includes
- # both the project name and a version string.
+ """Try to determine the version from the parent directory name.
+
+ Source tarballs conventionally unpack into a directory that includes
+ both the project name and a version string.
+ """
dirname = os.path.basename(root)
if not dirname.startswith(parentdir_prefix):
if verbose:
@@ -575,6 +603,7 @@ def versions_from_parentdir(parentdir_prefix, root, verbose):
@register_vcs_handler("git", "get_keywords")
def git_get_keywords(versionfile_abs):
+ """Extract version information from the given file."""
# the code embedded in _version.py can just fetch the value of these
# keywords. When used from setup.py, we don't want to import _version.py,
# so we do it with a regexp instead. This function is not used from
@@ -599,6 +628,7 @@ def git_get_keywords(versionfile_abs):
@register_vcs_handler("git", "keywords")
def git_versions_from_keywords(keywords, tag_prefix, verbose):
+ """Get version information from git keywords."""
if not keywords:
raise NotThisMethod("no keywords at all, weird")
refnames = keywords["refnames"].strip()
@@ -644,11 +674,12 @@ def git_versions_from_keywords(keywords, tag_prefix, verbose):
@register_vcs_handler("git", "pieces_from_vcs")
def git_pieces_from_vcs(tag_prefix, root, verbose, run_command=run_command):
- # this runs 'git' from the root of the source tree. This only gets called
- # if the git-archive 'subst' keywords were *not* expanded, and
- # _version.py hasn't already been rewritten with a short version string,
- # meaning we're inside a checked out source tree.
+ """Get version from 'git describe' in the root of the source tree.
+ This only gets called if the git-archive 'subst' keywords were *not*
+ expanded, and _version.py hasn't already been rewritten with a short
+ version string, meaning we're inside a checked out source tree.
+ """
if not os.path.exists(os.path.join(root, ".git")):
if verbose:
print("no .git in %%s" %% root)
@@ -657,10 +688,11 @@ def git_pieces_from_vcs(tag_prefix, root, verbose, run_command=run_command):
GITS = ["git"]
if sys.platform == "win32":
GITS = ["git.cmd", "git.exe"]
- # if there is a tag, this yields TAG-NUM-gHEX[-dirty]
- # if there are no tags, this yields HEX[-dirty] (no NUM)
+ # if there is a tag matching tag_prefix, this yields TAG-NUM-gHEX[-dirty]
+ # if there isn't one, this yields HEX[-dirty] (no NUM)
describe_out = run_command(GITS, ["describe", "--tags", "--dirty",
- "--always", "--long"],
+ "--always", "--long",
+ "--match", "%%s*" %% tag_prefix],
cwd=root)
# --long was added in git-1.5.5
if describe_out is None:
@@ -725,19 +757,21 @@ def git_pieces_from_vcs(tag_prefix, root, verbose, run_command=run_command):
def plus_or_dot(pieces):
+ """Return a + if we don't already have one, else return a ."""
if "+" in pieces.get("closest-tag", ""):
return "."
return "+"
def render_pep440(pieces):
- # now build up version string, with post-release "local version
- # identifier". Our goal: TAG[+DISTANCE.gHEX[.dirty]] . Note that if you
- # get a tagged build and then dirty it, you'll get TAG+0.gHEX.dirty
+ """Build up version string, with post-release "local version identifier".
- # exceptions:
- # 1: no tags. git_describe was just HEX. 0+untagged.DISTANCE.gHEX[.dirty]
+ Our goal: TAG[+DISTANCE.gHEX[.dirty]] . Note that if you
+ get a tagged build and then dirty it, you'll get TAG+0.gHEX.dirty
+ Exceptions:
+ 1: no tags. git_describe was just HEX. 0+untagged.DISTANCE.gHEX[.dirty]
+ """
if pieces["closest-tag"]:
rendered = pieces["closest-tag"]
if pieces["distance"] or pieces["dirty"]:
@@ -755,11 +789,11 @@ def render_pep440(pieces):
def render_pep440_pre(pieces):
- # TAG[.post.devDISTANCE] . No -dirty
-
- # exceptions:
- # 1: no tags. 0.post.devDISTANCE
+ """TAG[.post.devDISTANCE] -- No -dirty.
+ Exceptions:
+ 1: no tags. 0.post.devDISTANCE
+ """
if pieces["closest-tag"]:
rendered = pieces["closest-tag"]
if pieces["distance"]:
@@ -771,14 +805,15 @@ def render_pep440_pre(pieces):
def render_pep440_post(pieces):
- # TAG[.postDISTANCE[.dev0]+gHEX] . The ".dev0" means dirty. Note that
- # .dev0 sorts backwards (a dirty tree will appear "older" than the
- # corresponding clean one), but you shouldn't be releasing software with
- # -dirty anyways.
+ """TAG[.postDISTANCE[.dev0]+gHEX] .
- # exceptions:
- # 1: no tags. 0.postDISTANCE[.dev0]
+ The ".dev0" means dirty. Note that .dev0 sorts backwards
+ (a dirty tree will appear "older" than the corresponding clean one),
+ but you shouldn't be releasing software with -dirty anyways.
+ Exceptions:
+ 1: no tags. 0.postDISTANCE[.dev0]
+ """
if pieces["closest-tag"]:
rendered = pieces["closest-tag"]
if pieces["distance"] or pieces["dirty"]:
@@ -797,11 +832,13 @@ def render_pep440_post(pieces):
def render_pep440_old(pieces):
- # TAG[.postDISTANCE[.dev0]] . The ".dev0" means dirty.
+ """TAG[.postDISTANCE[.dev0]] .
- # exceptions:
- # 1: no tags. 0.postDISTANCE[.dev0]
+ The ".dev0" means dirty.
+ Eexceptions:
+ 1: no tags. 0.postDISTANCE[.dev0]
+ """
if pieces["closest-tag"]:
rendered = pieces["closest-tag"]
if pieces["distance"] or pieces["dirty"]:
@@ -817,12 +854,13 @@ def render_pep440_old(pieces):
def render_git_describe(pieces):
- # TAG[-DISTANCE-gHEX][-dirty], like 'git describe --tags --dirty
- # --always'
+ """TAG[-DISTANCE-gHEX][-dirty].
- # exceptions:
- # 1: no tags. HEX[-dirty] (note: no 'g' prefix)
+ Like 'git describe --tags --dirty --always'.
+ Exceptions:
+ 1: no tags. HEX[-dirty] (note: no 'g' prefix)
+ """
if pieces["closest-tag"]:
rendered = pieces["closest-tag"]
if pieces["distance"]:
@@ -836,12 +874,14 @@ def render_git_describe(pieces):
def render_git_describe_long(pieces):
- # TAG-DISTANCE-gHEX[-dirty], like 'git describe --tags --dirty
- # --always -long'. The distance/hash is unconditional.
+ """TAG-DISTANCE-gHEX[-dirty].
- # exceptions:
- # 1: no tags. HEX[-dirty] (note: no 'g' prefix)
+ Like 'git describe --tags --dirty --always -long'.
+ The distance/hash is unconditional.
+ Exceptions:
+ 1: no tags. HEX[-dirty] (note: no 'g' prefix)
+ """
if pieces["closest-tag"]:
rendered = pieces["closest-tag"]
rendered += "-%%d-g%%s" %% (pieces["distance"], pieces["short"])
@@ -854,6 +894,7 @@ def render_git_describe_long(pieces):
def render(pieces, style):
+ """Render the given version pieces into the requested style."""
if pieces["error"]:
return {"version": "unknown",
"full-revisionid": pieces.get("long"),
@@ -883,6 +924,7 @@ def render(pieces, style):
def get_versions():
+ """Get version information or return default if unable to do so."""
# I am in _version.py, which lives at ROOT/VERSIONFILE_SOURCE. If we have
# __file__, we can work backwards from there to the root. Some
# py2exe/bbfreeze/non-CPython implementations don't do __file__, in which
@@ -929,6 +971,7 @@ def get_versions():
@register_vcs_handler("git", "get_keywords")
def git_get_keywords(versionfile_abs):
+ """Extract version information from the given file."""
# the code embedded in _version.py can just fetch the value of these
# keywords. When used from setup.py, we don't want to import _version.py,
# so we do it with a regexp instead. This function is not used from
@@ -953,6 +996,7 @@ def git_get_keywords(versionfile_abs):
@register_vcs_handler("git", "keywords")
def git_versions_from_keywords(keywords, tag_prefix, verbose):
+ """Get version information from git keywords."""
if not keywords:
raise NotThisMethod("no keywords at all, weird")
refnames = keywords["refnames"].strip()
@@ -998,11 +1042,12 @@ def git_versions_from_keywords(keywords, tag_prefix, verbose):
@register_vcs_handler("git", "pieces_from_vcs")
def git_pieces_from_vcs(tag_prefix, root, verbose, run_command=run_command):
- # this runs 'git' from the root of the source tree. This only gets called
- # if the git-archive 'subst' keywords were *not* expanded, and
- # _version.py hasn't already been rewritten with a short version string,
- # meaning we're inside a checked out source tree.
+ """Get version from 'git describe' in the root of the source tree.
+ This only gets called if the git-archive 'subst' keywords were *not*
+ expanded, and _version.py hasn't already been rewritten with a short
+ version string, meaning we're inside a checked out source tree.
+ """
if not os.path.exists(os.path.join(root, ".git")):
if verbose:
print("no .git in %s" % root)
@@ -1011,10 +1056,11 @@ def git_pieces_from_vcs(tag_prefix, root, verbose, run_command=run_command):
GITS = ["git"]
if sys.platform == "win32":
GITS = ["git.cmd", "git.exe"]
- # if there is a tag, this yields TAG-NUM-gHEX[-dirty]
- # if there are no tags, this yields HEX[-dirty] (no NUM)
+ # if there is a tag matching tag_prefix, this yields TAG-NUM-gHEX[-dirty]
+ # if there isn't one, this yields HEX[-dirty] (no NUM)
describe_out = run_command(GITS, ["describe", "--tags", "--dirty",
- "--always", "--long"],
+ "--always", "--long",
+ "--match", "%s*" % tag_prefix],
cwd=root)
# --long was added in git-1.5.5
if describe_out is None:
@@ -1079,6 +1125,11 @@ def git_pieces_from_vcs(tag_prefix, root, verbose, run_command=run_command):
def do_vcs_install(manifest_in, versionfile_source, ipy):
+ """Git-specific installation logic for Versioneer.
+
+ For Git, this means creating/changing .gitattributes to mark _version.py
+ for export-time keyword substitution.
+ """
GITS = ["git"]
if sys.platform == "win32":
GITS = ["git.cmd", "git.exe"]
@@ -1112,8 +1163,11 @@ def do_vcs_install(manifest_in, versionfile_source, ipy):
def versions_from_parentdir(parentdir_prefix, root, verbose):
- # Source tarballs conventionally unpack into a directory that includes
- # both the project name and a version string.
+ """Try to determine the version from the parent directory name.
+
+ Source tarballs conventionally unpack into a directory that includes
+ both the project name and a version string.
+ """
dirname = os.path.basename(root)
if not dirname.startswith(parentdir_prefix):
if verbose:
@@ -1125,7 +1179,7 @@ def versions_from_parentdir(parentdir_prefix, root, verbose):
"dirty": False, "error": None}
SHORT_VERSION_PY = """
-# This file was generated by 'versioneer.py' (0.15) from
+# This file was generated by 'versioneer.py' (0.16) from
# revision-control system data, or from the parent directory name of an
# unpacked source archive. Distribution tarballs contain a pre-generated copy
# of this file.
@@ -1144,6 +1198,7 @@ def get_versions():
def versions_from_file(filename):
+ """Try to determine the version from _version.py if present."""
try:
with open(filename) as f:
contents = f.read()
@@ -1157,6 +1212,7 @@ def versions_from_file(filename):
def write_to_version_file(filename, versions):
+ """Write the given version number to the given _version.py file."""
os.unlink(filename)
contents = json.dumps(versions, sort_keys=True,
indent=1, separators=(",", ": "))
@@ -1167,19 +1223,21 @@ def write_to_version_file(filename, versions):
def plus_or_dot(pieces):
+ """Return a + if we don't already have one, else return a ."""
if "+" in pieces.get("closest-tag", ""):
return "."
return "+"
def render_pep440(pieces):
- # now build up version string, with post-release "local version
- # identifier". Our goal: TAG[+DISTANCE.gHEX[.dirty]] . Note that if you
- # get a tagged build and then dirty it, you'll get TAG+0.gHEX.dirty
+ """Build up version string, with post-release "local version identifier".
- # exceptions:
- # 1: no tags. git_describe was just HEX. 0+untagged.DISTANCE.gHEX[.dirty]
+ Our goal: TAG[+DISTANCE.gHEX[.dirty]] . Note that if you
+ get a tagged build and then dirty it, you'll get TAG+0.gHEX.dirty
+ Exceptions:
+ 1: no tags. git_describe was just HEX. 0+untagged.DISTANCE.gHEX[.dirty]
+ """
if pieces["closest-tag"]:
rendered = pieces["closest-tag"]
if pieces["distance"] or pieces["dirty"]:
@@ -1197,11 +1255,11 @@ def render_pep440(pieces):
def render_pep440_pre(pieces):
- # TAG[.post.devDISTANCE] . No -dirty
-
- # exceptions:
- # 1: no tags. 0.post.devDISTANCE
+ """TAG[.post.devDISTANCE] -- No -dirty.
+ Exceptions:
+ 1: no tags. 0.post.devDISTANCE
+ """
if pieces["closest-tag"]:
rendered = pieces["closest-tag"]
if pieces["distance"]:
@@ -1213,14 +1271,15 @@ def render_pep440_pre(pieces):
def render_pep440_post(pieces):
- # TAG[.postDISTANCE[.dev0]+gHEX] . The ".dev0" means dirty. Note that
- # .dev0 sorts backwards (a dirty tree will appear "older" than the
- # corresponding clean one), but you shouldn't be releasing software with
- # -dirty anyways.
+ """TAG[.postDISTANCE[.dev0]+gHEX] .
- # exceptions:
- # 1: no tags. 0.postDISTANCE[.dev0]
+ The ".dev0" means dirty. Note that .dev0 sorts backwards
+ (a dirty tree will appear "older" than the corresponding clean one),
+ but you shouldn't be releasing software with -dirty anyways.
+ Exceptions:
+ 1: no tags. 0.postDISTANCE[.dev0]
+ """
if pieces["closest-tag"]:
rendered = pieces["closest-tag"]
if pieces["distance"] or pieces["dirty"]:
@@ -1239,11 +1298,13 @@ def render_pep440_post(pieces):
def render_pep440_old(pieces):
- # TAG[.postDISTANCE[.dev0]] . The ".dev0" means dirty.
+ """TAG[.postDISTANCE[.dev0]] .
- # exceptions:
- # 1: no tags. 0.postDISTANCE[.dev0]
+ The ".dev0" means dirty.
+ Eexceptions:
+ 1: no tags. 0.postDISTANCE[.dev0]
+ """
if pieces["closest-tag"]:
rendered = pieces["closest-tag"]
if pieces["distance"] or pieces["dirty"]:
@@ -1259,12 +1320,13 @@ def render_pep440_old(pieces):
def render_git_describe(pieces):
- # TAG[-DISTANCE-gHEX][-dirty], like 'git describe --tags --dirty
- # --always'
+ """TAG[-DISTANCE-gHEX][-dirty].
- # exceptions:
- # 1: no tags. HEX[-dirty] (note: no 'g' prefix)
+ Like 'git describe --tags --dirty --always'.
+ Exceptions:
+ 1: no tags. HEX[-dirty] (note: no 'g' prefix)
+ """
if pieces["closest-tag"]:
rendered = pieces["closest-tag"]
if pieces["distance"]:
@@ -1278,12 +1340,14 @@ def render_git_describe(pieces):
def render_git_describe_long(pieces):
- # TAG-DISTANCE-gHEX[-dirty], like 'git describe --tags --dirty
- # --always -long'. The distance/hash is unconditional.
+ """TAG-DISTANCE-gHEX[-dirty].
- # exceptions:
- # 1: no tags. HEX[-dirty] (note: no 'g' prefix)
+ Like 'git describe --tags --dirty --always -long'.
+ The distance/hash is unconditional.
+ Exceptions:
+ 1: no tags. HEX[-dirty] (note: no 'g' prefix)
+ """
if pieces["closest-tag"]:
rendered = pieces["closest-tag"]
rendered += "-%d-g%s" % (pieces["distance"], pieces["short"])
@@ -1296,6 +1360,7 @@ def render_git_describe_long(pieces):
def render(pieces, style):
+ """Render the given version pieces into the requested style."""
if pieces["error"]:
return {"version": "unknown",
"full-revisionid": pieces.get("long"),
@@ -1325,12 +1390,14 @@ def render(pieces, style):
class VersioneerBadRootError(Exception):
- pass
+ """The project root directory is unknown or missing key files."""
def get_versions(verbose=False):
- # returns dict with two keys: 'version' and 'full'
+ """Get the project version from whatever source is available.
+ Returns dict with two keys: 'version' and 'full'.
+ """
if "versioneer" in sys.modules:
# see the discussion in cmdclass.py:get_cmdclass()
del sys.modules["versioneer"]
@@ -1402,10 +1469,12 @@ def get_versions(verbose=False):
def get_version():
+ """Get the short version string for this project."""
return get_versions()["version"]
def get_cmdclass():
+ """Get the custom setuptools/distutils subclasses used by Versioneer."""
if "versioneer" in sys.modules:
del sys.modules["versioneer"]
# this fixes the "python setup.py develop" case (also 'install' and
@@ -1456,7 +1525,11 @@ def get_cmdclass():
# setuptools/install -> bdist_egg ->..
# setuptools/develop -> ?
- from distutils.command.build_py import build_py as _build_py
+ # we override different "build_py" commands for both environments
+ if "setuptools" in sys.modules:
+ from setuptools.command.build_py import build_py as _build_py
+ else:
+ from distutils.command.build_py import build_py as _build_py
class cmd_build_py(_build_py):
@@ -1542,7 +1615,7 @@ a section like:
style = pep440
versionfile_source = src/myproject/_version.py
versionfile_build = myproject/_version.py
- tag_prefix = ""
+ tag_prefix =
parentdir_prefix = myproject-
You will also need to edit your setup.py to use the results:
@@ -1578,6 +1651,7 @@ del get_versions
def do_setup():
+ """Main VCS-independent setup function for installing Versioneer."""
root = get_root()
try:
cfg = get_config_from_root(root)
@@ -1659,6 +1733,7 @@ def do_setup():
def scan_setup_py():
+ """Validate the contents of setup.py against Versioneer's expectations."""
found = set()
setters = False
errors = 0
--
cgit v1.2.3
From 0ce1c02dd59df3e4f23ba0b90e67644258412533 Mon Sep 17 00:00:00 2001
From: Kali Kaneko
Date: Mon, 4 Apr 2016 21:55:06 -0400
Subject: [bug] fail gracefully if no pixelated modules present
currently, we're distributing the wheels for the pixelated modules under
downloads.leap.se.
bootstrap script tried to download the pixelated modules, but it fails
on python versions < 2.7.9, apparently.
as a workaround, I make the import of the pixelated modules a non-fatal
error by setting a flag, and doing the launching of the pix UA
conditional on a successful import.
- Related: #8009
---
pkg/scripts/bootstrap_develop.sh | 3 ++-
src/leap/bitmask/backend/components.py | 14 ++++++++------
src/leap/bitmask/pix.py | 26 +++++++++++++++-----------
3 files changed, 25 insertions(+), 18 deletions(-)
diff --git a/pkg/scripts/bootstrap_develop.sh b/pkg/scripts/bootstrap_develop.sh
index 3695fabc..af3dce20 100755
--- a/pkg/scripts/bootstrap_develop.sh
+++ b/pkg/scripts/bootstrap_develop.sh
@@ -118,7 +118,8 @@ setup_develop() {
# hack to solve gnupg version problem
pip uninstall -y gnupg && pip install gnupg
- pip install -r pkg/requirements-pixelated.pip
+ # XXX this fails in trusty; see #8009
+ # pip install -r pkg/requirements-pixelated.pip
set +x
echo "${cc_green}Status: $status done.${cc_normal}"
}
diff --git a/src/leap/bitmask/backend/components.py b/src/leap/bitmask/backend/components.py
index 0f8864c3..0c2b3280 100644
--- a/src/leap/bitmask/backend/components.py
+++ b/src/leap/bitmask/backend/components.py
@@ -38,7 +38,7 @@ from leap.bitmask.crypto.srpauth import SRPAuth
from leap.bitmask.crypto.srpregister import SRPRegister
from leap.bitmask.logs.utils import get_logger
from leap.bitmask.platform_init import IS_LINUX
-from leap.bitmask.pix import start_pixelated_user_agent
+from leap.bitmask import pix
from leap.bitmask.provider.pinned import PinnedProviders
from leap.bitmask.provider.providerbootstrapper import ProviderBootstrapper
from leap.bitmask.services import get_supported
@@ -1088,13 +1088,15 @@ class Mail(object):
return threads.deferToThread(self._stop_imap_service)
def start_pixelated_service(self, full_user_id):
- reactor.callFromThread(
- start_pixelated_user_agent,
- full_user_id,
- self._soledad_proxy,
- self._keymanager_proxy)
+ if pix.HAS_PIXELATED:
+ reactor.callFromThread(
+ pix.start_pixelated_user_agent,
+ full_user_id,
+ self._soledad_proxy,
+ self._keymanager_proxy)
def stop_pixelated_service(self):
+ # TODO stop it, somehow
pass
diff --git a/src/leap/bitmask/pix.py b/src/leap/bitmask/pix.py
index 8242255c..a05a1d9c 100644
--- a/src/leap/bitmask/pix.py
+++ b/src/leap/bitmask/pix.py
@@ -27,17 +27,21 @@ from twisted.python import log
from leap.bitmask.util import get_path_prefix
from leap.mail.imap.account import IMAPAccount
-import pixelated_www
-
-from pixelated.adapter.mailstore import LeapMailStore
-from pixelated.adapter.welcome_mail import add_welcome_mail
-from pixelated.application import SingleUserServicesFactory
-from pixelated.application import UserAgentMode
-from pixelated.application import start_site
-from pixelated.bitmask_libraries.smtp import LeapSMTPConfig
-from pixelated.bitmask_libraries.session import SessionCache
-from pixelated.config import services
-from pixelated.resources.root_resource import RootResource
+try:
+ import pixelated_www
+
+ from pixelated.adapter.mailstore import LeapMailStore
+ from pixelated.adapter.welcome_mail import add_welcome_mail
+ from pixelated.application import SingleUserServicesFactory
+ from pixelated.application import UserAgentMode
+ from pixelated.application import start_site
+ from pixelated.bitmask_libraries.smtp import LeapSMTPConfig
+ from pixelated.bitmask_libraries.session import SessionCache
+ from pixelated.config import services
+ from pixelated.resources.root_resource import RootResource
+ HAS_PIXELATED = True
+except ImportError:
+ HAS_PIXELATED = False
def start_pixelated_user_agent(userid, soledad, keymanager):
--
cgit v1.2.3
From 093f84e42192fd8dc2234a00b754515be7ea9016 Mon Sep 17 00:00:00 2001
From: Kali Kaneko
Date: Mon, 4 Apr 2016 17:51:30 -0400
Subject: [pkg] simple launcher for the linux bundles
---
pkg/launcher/.gitignore | 2 ++
pkg/launcher/Makefile | 15 +++++++++++++++
pkg/launcher/README.rst | 14 ++++++++++++++
pkg/launcher/bitmask-launcher.c | 23 +++++++++++++++++++++++
4 files changed, 54 insertions(+)
create mode 100644 pkg/launcher/.gitignore
create mode 100644 pkg/launcher/Makefile
create mode 100644 pkg/launcher/README.rst
create mode 100644 pkg/launcher/bitmask-launcher.c
diff --git a/pkg/launcher/.gitignore b/pkg/launcher/.gitignore
new file mode 100644
index 00000000..60de46d7
--- /dev/null
+++ b/pkg/launcher/.gitignore
@@ -0,0 +1,2 @@
+*.o
+bitmask
diff --git a/pkg/launcher/Makefile b/pkg/launcher/Makefile
new file mode 100644
index 00000000..8dd1013d
--- /dev/null
+++ b/pkg/launcher/Makefile
@@ -0,0 +1,15 @@
+CC = gcc
+CFLAGS = -g -Wall
+STRIP = strip
+
+default: bitmask
+
+bitmask.o: bitmask-launcher.c
+ $(CC) $(CFLAGS) -c bitmask-launcher.c -o bitmask.o
+
+bitmask: bitmask.o
+ $(CC) bitmask.o -o bitmask
+ $(STRIP) bitmask
+clean:
+ -rm -f bitmask.o
+ -rm -f bitmask
diff --git a/pkg/launcher/README.rst b/pkg/launcher/README.rst
new file mode 100644
index 00000000..9a840dec
--- /dev/null
+++ b/pkg/launcher/README.rst
@@ -0,0 +1,14 @@
+bitmask-launcher.c
+------------------
+
+A small, portable launcher for bitmask bundles.
+
+Problem that solves
+-------------------
+PyInstaller bundles leave everything (libs, data and the main binary) in a
+single folder. In a case like ours, there are too many files cluttering this
+top-most folder.
+
+We wanted to have a cleaner folder, with an obviously clickable entrypoint, that
+calls the binary that hides in an inferior folder.
+
diff --git a/pkg/launcher/bitmask-launcher.c b/pkg/launcher/bitmask-launcher.c
new file mode 100644
index 00000000..aac5da3f
--- /dev/null
+++ b/pkg/launcher/bitmask-launcher.c
@@ -0,0 +1,23 @@
+/*
+ * bitmask-launcher.c
+ *
+ * part of the bitmask bundle.
+ * execute main entrypoint in a child folder inside the bundle.
+ *
+ * (c) LEAP Encryption Access Project, 2016.
+ * License: GPL.
+ *
+*/
+
+#include
+#include
+
+char* const bitmask_path = "libs";
+char* const entrypoint = "bitmask";
+
+int main(int argc, char *argv[])
+{
+ argv[0] = entrypoint;
+ chdir(bitmask_path);
+ execv(entrypoint, argv);
+}
--
cgit v1.2.3
From b4dde3d5112c95574f85f62daf0c2c75db391f52 Mon Sep 17 00:00:00 2001
From: Kali Kaneko
Date: Mon, 4 Apr 2016 22:19:52 -0400
Subject: [pkg] modularize main makefile to remove clutter
---
Makefile | 67 ++--------------------------------------------
pkg/pyinst/pyinst-build.mk | 39 +++++++++++++++++++++++++++
pkg/sumo-tarballs.mk | 25 +++++++++++++++++
3 files changed, 66 insertions(+), 65 deletions(-)
create mode 100644 pkg/pyinst/pyinst-build.mk
create mode 100644 pkg/sumo-tarballs.mk
diff --git a/Makefile b/Makefile
index c3f0e0d2..fea03951 100644
--- a/Makefile
+++ b/Makefile
@@ -141,71 +141,8 @@ checkout_leapdeps_develop:
for repo in $(LEAP_REPOS); do cd $(CURDIR)/../$$repo && git checkout develop; done
git checkout develop
-checkout_leapdeps_release:
- pkg/scripts/checkout_leap_versions.sh
-
-setup_without_namespace:
- awk '!/namespace_packages*/' setup.py > file && mv file setup.py
-
-sumo_tarball_release: checkout_leapdeps_release setup_without_namespace
- python setup.py sdist --sumo
- git checkout -- src/leap/__init__.py
- git checkout -- src/leap/bitmask/_version.py
- rm -rf src/leap/soledad
- git checkout -- setup.py
-
-# XXX We need two sets of sumo-tarballs: the one published for a release
-# (that will pick the pinned leap deps), and the other which will be used
-# for the nightly builds.
-# TODO change naming scheme for sumo-latest: should include date (in case
-# bitmask is not updated bu the dependencies are)
-
-sumo_tarball_latest: checkout_leapdeps_develop pull_leapdeps setup_without_namespace
- python setup.py sdist --sumo # --latest
- git checkout -- src/leap/__init__.py
- git checkout -- src/leap/bitmask/_version.py
- rm -rf src/leap/soledad
- git checkout -- setup.py
-
-pyinst:
- echo "MAKE SURE OF FREEZING VERSION FIRST!"
- pyinstaller -y pkg/pyinst/bitmask.spec
-
-pyinst-hacks:
- cp ../leap_common/src/leap/common/cacert.pem $(DIST)
- mkdir -p $(DIST)pysqlcipher
- cp $(VIRTUAL_ENV)/lib/python2.7/site-packages/pysqlcipher/_sqlite.so $(DIST)pysqlcipher
- cp -r $(VIRTUAL_ENV)/lib/python2.7/site-packages/pixelated_www $(DIST)
-
-pyinst-trim:
- rm -f $(DIST)libQtOpenGL.so.4
- rm -f $(DIST)libQtSql.so.4
- rm -f $(DIST)libQt3Support.so.4
- rm -f $(DIST)libaudio.so.2
- rm -f $(DIST)libnvidia-*
- #rm -f dist/bitmask/libgstvideo-1.0.so.0
- #rm -f dist/bitmask/libgstaudio0.0.so.0
- #rm -f dist/bitmask/libgstreamer-1.0.so.0
-
-pyinst-wrapper:
- mv $(DIST)libQtCore.so.4 $(DIST)libQtCore.so.4.orig
- mv $(DIST)libQtGui.so.4 $(DIST)libQtGui.so.4.orig
- mv $(DIST)libQtNetwork.so.4 $(DIST)libQtNetwork.so.4.orig
- mv $(DIST)libQtSvg.so.4 $(DIST)libQtSvg.so.4.orig
- mv $(DIST)libQtWebKit.so.4 $(DIST)libQtWebKit.so.4.orig
- mv $(DIST)libQtXmlPatterns.so.4 $(DIST)libQtXmlPatterns.so.4.orig
- mv $(DIST)libQtXml.so.4 $(DIST)libQtXml.so.4.orig
- mv $(DIST)bitmask $(DIST)bitmask-app
- cp pkg/linux/bitmask-launcher $(DIST)bitmask
- cp pkg/PixelatedWebmail.README $(DIST)
-
-
-pyinst-dist:
- rm -rf $(DIST)config
- cd dist/ && tar cvzf Bitmask.0.9.2.alpha2.tar.gz bitmask
-
-clean_pkg:
- rm -rf build dist
+include pkg/sumo-tarballs.mk
+include pkg/pyinst/pyinst-build.mk
clean :
$(RM) $(COMPILED_UI) $(COMPILED_RESOURCES) $(COMPILED_UI:.py=.pyc) $(COMPILED_RESOURCES:.py=.pyc)
diff --git a/pkg/pyinst/pyinst-build.mk b/pkg/pyinst/pyinst-build.mk
new file mode 100644
index 00000000..532ec88c
--- /dev/null
+++ b/pkg/pyinst/pyinst-build.mk
@@ -0,0 +1,39 @@
+pyinst:
+ echo "MAKE SURE OF FREEZING VERSION FIRST!"
+ pyinstaller -y pkg/pyinst/bitmask.spec
+
+pyinst-hacks:
+ cp ../leap_common/src/leap/common/cacert.pem $(DIST)
+ mkdir -p $(DIST)pysqlcipher
+ cp $(VIRTUAL_ENV)/lib/python2.7/site-packages/pysqlcipher/_sqlite.so $(DIST)pysqlcipher
+ cp -r $(VIRTUAL_ENV)/lib/python2.7/site-packages/pixelated_www $(DIST)
+
+pyinst-trim:
+ rm -f $(DIST)libQtOpenGL.so.4
+ rm -f $(DIST)libQtSql.so.4
+ rm -f $(DIST)libQt3Support.so.4
+ rm -f $(DIST)libaudio.so.2
+ rm -f $(DIST)libnvidia-*
+ #rm -f dist/bitmask/libgstvideo-1.0.so.0
+ #rm -f dist/bitmask/libgstaudio0.0.so.0
+ #rm -f dist/bitmask/libgstreamer-1.0.so.0
+
+pyinst-wrapper:
+ mv $(DIST)libQtCore.so.4 $(DIST)libQtCore.so.4.orig
+ mv $(DIST)libQtGui.so.4 $(DIST)libQtGui.so.4.orig
+ mv $(DIST)libQtNetwork.so.4 $(DIST)libQtNetwork.so.4.orig
+ mv $(DIST)libQtSvg.so.4 $(DIST)libQtSvg.so.4.orig
+ mv $(DIST)libQtWebKit.so.4 $(DIST)libQtWebKit.so.4.orig
+ mv $(DIST)libQtXmlPatterns.so.4 $(DIST)libQtXmlPatterns.so.4.orig
+ mv $(DIST)libQtXml.so.4 $(DIST)libQtXml.so.4.orig
+ mv $(DIST)bitmask $(DIST)bitmask-app
+ cp pkg/linux/bitmask-launcher $(DIST)bitmask
+ cp pkg/PixelatedWebmail.README $(DIST)
+
+
+pyinst-dist:
+ rm -rf $(DIST)config
+ cd dist/ && tar cvzf Bitmask.0.9.2.alpha2.tar.gz bitmask
+
+clean_pkg:
+ rm -rf build dist
diff --git a/pkg/sumo-tarballs.mk b/pkg/sumo-tarballs.mk
new file mode 100644
index 00000000..3bd5fa77
--- /dev/null
+++ b/pkg/sumo-tarballs.mk
@@ -0,0 +1,25 @@
+checkout_leapdeps_release:
+ pkg/scripts/checkout_leap_versions.sh
+
+setup_without_namespace:
+ awk '!/namespace_packages*/' setup.py > file && mv file setup.py
+
+sumo_tarball_release: checkout_leapdeps_release setup_without_namespace
+ python setup.py sdist --sumo
+ git checkout -- src/leap/__init__.py
+ git checkout -- src/leap/bitmask/_version.py
+ rm -rf src/leap/soledad
+ git checkout -- setup.py
+
+# XXX We need two sets of sumo-tarballs: the one published for a release
+# (that will pick the pinned leap deps), and the other which will be used
+# for the nightly builds.
+# TODO change naming scheme for sumo-latest: should include date (in case
+# bitmask is not updated bu the dependencies are)
+
+sumo_tarball_latest: checkout_leapdeps_develop pull_leapdeps setup_without_namespace
+ python setup.py sdist --sumo # --latest
+ git checkout -- src/leap/__init__.py
+ git checkout -- src/leap/bitmask/_version.py
+ rm -rf src/leap/soledad
+ git checkout -- setup.py
--
cgit v1.2.3
From c35d9f6338300dcf6f1688ee2df9475dd14b8c94 Mon Sep 17 00:00:00 2001
From: Kali Kaneko
Date: Mon, 4 Apr 2016 22:49:56 -0400
Subject: [pkg] move the pyinstaller bundle to a child folder
---
Makefile | 3 +++
docs/release_checklist.wiki | 3 ++-
pkg/next-version | 1 +
pkg/pyinst/pyinst-build.mk | 27 ++++++++++++++++++++++-----
4 files changed, 28 insertions(+), 6 deletions(-)
create mode 100644 pkg/next-version
diff --git a/Makefile b/Makefile
index fea03951..6a8fbecb 100644
--- a/Makefile
+++ b/Makefile
@@ -41,7 +41,10 @@ PYLUP = pyside-lupdate
LRELE = lrelease
# pyinst dist dir
+
DIST = dist/bitmask/
+NEXT_VERSION = $(shell cat pkg/next-version)
+DIST_VERSION = dist/bitmask-$(NEXT_VERSION)/
#################################
diff --git a/docs/release_checklist.wiki b/docs/release_checklist.wiki
index 075591a7..f831d965 100644
--- a/docs/release_checklist.wiki
+++ b/docs/release_checklist.wiki
@@ -1,6 +1,7 @@
= Bitmask Release Checklist (*) =
* [ ] Check that all tests are passing!
* [ ] Check that the version in bitmask_client/pkg/linux/bitmask-root is bumped if needed.
+ * [ ] Update pkg/next-release
* [ ] Tag everything
* Should be done for the following packages, in order:
* [ ] 1. leap.common
@@ -31,7 +32,7 @@
* [ ] git push origin master; git push origin X.Y.Z
* [ ] git checkout develop && git merge master && git push origin develop
* [ ] Build and upload bundles
- * [ ] Use the scripts under pkg// to build the the bundles.
+ * [ ] Use 'make pyinst-linux' to build bundles.
* [ ] Sign them with gpg -a --sign --detach-sign
* [ ] Upload bundle and signature to downloads.leap.se/client//Bitmask--.(tar.bz2,dmg,zip)
* [ ] Update symbolic link for latest upload and signature:
diff --git a/pkg/next-version b/pkg/next-version
new file mode 100644
index 00000000..8df8fe62
--- /dev/null
+++ b/pkg/next-version
@@ -0,0 +1 @@
+0.9.2.alpha3
diff --git a/pkg/pyinst/pyinst-build.mk b/pkg/pyinst/pyinst-build.mk
index 532ec88c..637390a8 100644
--- a/pkg/pyinst/pyinst-build.mk
+++ b/pkg/pyinst/pyinst-build.mk
@@ -1,5 +1,7 @@
pyinst:
- echo "MAKE SURE OF FREEZING VERSION FIRST!"
+ echo "*********************************************"
+ echo "MAKE SURE OF MANUALLY FREEZING VERSION FIRST!"
+ echo "*********************************************"
pyinstaller -y pkg/pyinst/bitmask.spec
pyinst-hacks:
@@ -19,6 +21,7 @@ pyinst-trim:
#rm -f dist/bitmask/libgstreamer-1.0.so.0
pyinst-wrapper:
+ # TODO this *is* an ugly hack, See #7352
mv $(DIST)libQtCore.so.4 $(DIST)libQtCore.so.4.orig
mv $(DIST)libQtGui.so.4 $(DIST)libQtGui.so.4.orig
mv $(DIST)libQtNetwork.so.4 $(DIST)libQtNetwork.so.4.orig
@@ -28,12 +31,26 @@ pyinst-wrapper:
mv $(DIST)libQtXml.so.4 $(DIST)libQtXml.so.4.orig
mv $(DIST)bitmask $(DIST)bitmask-app
cp pkg/linux/bitmask-launcher $(DIST)bitmask
- cp pkg/PixelatedWebmail.README $(DIST)
-
-pyinst-dist:
+pyinst-cleanup:
rm -rf $(DIST)config
- cd dist/ && tar cvzf Bitmask.0.9.2.alpha2.tar.gz bitmask
+ mkdir -p $(DIST_VERSION)
+ mv $(DIST) $(DIST_VERSION)libs
+ cd pkg/launcher && make
+ mv pkg/launcher/bitmask $(DIST_VERSION)
+
+pyinst-distribution-data:
+ cp release-notes.rst $(DIST_VERSION)
+ cp pkg/PixelatedWebmail.README $(DIST_VERSION)
+ cp LICENSE $(DIST_VERSION)
+
+pyinst-tar:
+ cd dist/ && tar cvzf Bitmask.$(NEXT_VERSION).tar.gz bitmask-$(NEXT_VERSION)
+
+pyinst-sign:
+ # TODO ---- get LEAP_MAINTAINER from environment
+
+pyinst-linux: pyinst pyinst-hacks pyinst-trim pyinst-wrapper pyinst-cleanup pyinst-distribution-data pyinst-tar
clean_pkg:
rm -rf build dist
--
cgit v1.2.3
From bb0dd2d30c7408cf3a50bafd8085aa69ca02e4f2 Mon Sep 17 00:00:00 2001
From: Kali Kaneko
Date: Wed, 6 Apr 2016 15:39:55 -0400
Subject: [pkg] add standalone flag if running inside a frozen bin
---
src/leap/bitmask/app.py | 3 +++
1 file changed, 3 insertions(+)
diff --git a/src/leap/bitmask/app.py b/src/leap/bitmask/app.py
index dc1ee6df..0c4c32e2 100644
--- a/src/leap/bitmask/app.py
+++ b/src/leap/bitmask/app.py
@@ -163,6 +163,9 @@ def start_app():
}
flags.STANDALONE = opts.standalone
+ if getattr(sys, 'frozen', False):
+ flags.STANDALONE = True
+
flags.OFFLINE = opts.offline
flags.MAIL_LOGFILE = opts.mail_log_file
flags.APP_VERSION_CHECK = opts.app_version_check
--
cgit v1.2.3
From 40604c0b2abe4d51e5e7b41a0e71c78a958b0b87 Mon Sep 17 00:00:00 2001
From: Kali Kaneko
Date: Wed, 6 Apr 2016 16:02:11 -0400
Subject: [pkg] copy helpers, freeze version
---
Makefile | 1 +
pkg/pyinst/pyinst-build.mk | 32 ++++++++++++++++++++++++++------
pkg/version-template | 8 ++++++++
3 files changed, 35 insertions(+), 6 deletions(-)
create mode 100644 pkg/version-template
diff --git a/Makefile b/Makefile
index 6a8fbecb..f96d810d 100644
--- a/Makefile
+++ b/Makefile
@@ -45,6 +45,7 @@ LRELE = lrelease
DIST = dist/bitmask/
NEXT_VERSION = $(shell cat pkg/next-version)
DIST_VERSION = dist/bitmask-$(NEXT_VERSION)/
+GIT_COMMIT = $(shell git rev-parse HEAD)
#################################
diff --git a/pkg/pyinst/pyinst-build.mk b/pkg/pyinst/pyinst-build.mk
index 637390a8..a14f2a8d 100644
--- a/pkg/pyinst/pyinst-build.mk
+++ b/pkg/pyinst/pyinst-build.mk
@@ -1,9 +1,14 @@
-pyinst:
- echo "*********************************************"
- echo "MAKE SURE OF MANUALLY FREEZING VERSION FIRST!"
- echo "*********************************************"
+freeze-ver:
+ cp pkg/version-template src/leap/bitmask/_version.py
+ sed -i 's/^version_version\(.*\)/version_version = "$(NEXT_VERSION)"/' src/leap/bitmask/_version.py
+ sed -i 's/^full_revisionid\(.*\)/full_revisionid = "$(GIT_COMMIT)"/' src/leap/bitmask/_version.py
+
+pyinst: freeze-ver
pyinstaller -y pkg/pyinst/bitmask.spec
+reset-ver:
+ git checkout -- src/leap/bitmask/_version.py
+
pyinst-hacks:
cp ../leap_common/src/leap/common/cacert.pem $(DIST)
mkdir -p $(DIST)pysqlcipher
@@ -44,13 +49,28 @@ pyinst-distribution-data:
cp pkg/PixelatedWebmail.README $(DIST_VERSION)
cp LICENSE $(DIST_VERSION)
+pyinst-linux-helpers:
+ mkdir -p $(DIST_VERSION)apps/eip/files
+ # TODO compile static
+ cp /usr/sbin/openvpn $(DIST_VERSION)apps/eip/files/leap-openvpn
+ cp pkg/linux/bitmask-root $(DIST_VERSION)apps/eip/files/
+ cp pkg/linux/leap-install-helper.sh $(DIST_VERSION)apps/eip/files/
+ cp pkg/linux/polkit/se.leap.bitmask.bundle.policy $(DIST_VERSION)apps/eip/files/
+ mkdir -p $(DIST_VERSION)apps/mail
+ # TODO compile static
+ cp /usr/bin/gpg $(DIST_VERSION)apps/mail
+
pyinst-tar:
cd dist/ && tar cvzf Bitmask.$(NEXT_VERSION).tar.gz bitmask-$(NEXT_VERSION)
pyinst-sign:
- # TODO ---- get LEAP_MAINTAINER from environment
+ gpg2 -a --sign --detach-sign dist/Bitmask.$(NEXT_VERSION).tar.gz
+
+pyinst-upload:
+ scp dist/Bitmask.$(NEXT_VERSION).* salmon.leap.se:./
-pyinst-linux: pyinst pyinst-hacks pyinst-trim pyinst-wrapper pyinst-cleanup pyinst-distribution-data pyinst-tar
+#pyinst-linux: pyinst pyinst-hacks pyinst-trim pyinst-wrapper pyinst-cleanup pyinst-distribution-data pyinst-tar
+pyinst-linux: pyinst reset-ver pyinst-hacks pyinst-trim pyinst-cleanup pyinst-distribution-data pyinst-linux-helpers pyinst-tar
clean_pkg:
rm -rf build dist
diff --git a/pkg/version-template b/pkg/version-template
new file mode 100644
index 00000000..ecb5b987
--- /dev/null
+++ b/pkg/version-template
@@ -0,0 +1,8 @@
+version_version = "xxx"
+full_revisionid = 'deadbeef'
+
+
+def get_versions(default={}, verbose=False):
+ return {'version': version_version,
+ 'full-revisionid': full_revisionid}
+
--
cgit v1.2.3
From 8836413ae5d0d22bca3c512ff4164d7559f9ada9 Mon Sep 17 00:00:00 2001
From: Kali Kaneko
Date: Wed, 6 Apr 2016 16:07:29 -0400
Subject: typo: mimmick older bundles path
---
pkg/launcher/bitmask-launcher.c | 2 +-
pkg/pyinst/pyinst-build.mk | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/pkg/launcher/bitmask-launcher.c b/pkg/launcher/bitmask-launcher.c
index aac5da3f..cf5c2a18 100644
--- a/pkg/launcher/bitmask-launcher.c
+++ b/pkg/launcher/bitmask-launcher.c
@@ -12,7 +12,7 @@
#include
#include
-char* const bitmask_path = "libs";
+char* const bitmask_path = "lib";
char* const entrypoint = "bitmask";
int main(int argc, char *argv[])
diff --git a/pkg/pyinst/pyinst-build.mk b/pkg/pyinst/pyinst-build.mk
index a14f2a8d..16737ead 100644
--- a/pkg/pyinst/pyinst-build.mk
+++ b/pkg/pyinst/pyinst-build.mk
@@ -40,7 +40,7 @@ pyinst-wrapper:
pyinst-cleanup:
rm -rf $(DIST)config
mkdir -p $(DIST_VERSION)
- mv $(DIST) $(DIST_VERSION)libs
+ mv $(DIST) $(DIST_VERSION)lib
cd pkg/launcher && make
mv pkg/launcher/bitmask $(DIST_VERSION)
--
cgit v1.2.3
From e420ba19f79cf80c462ebdcf694a7cec453c73b2 Mon Sep 17 00:00:00 2001
From: Kali Kaneko
Date: Wed, 6 Apr 2016 16:10:42 -0400
Subject: [pkg] adjust for the new cwd() inside bundle
---
src/leap/bitmask/platform_init/initializers.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/leap/bitmask/platform_init/initializers.py b/src/leap/bitmask/platform_init/initializers.py
index 4e8bbdbb..f0ec2d53 100644
--- a/src/leap/bitmask/platform_init/initializers.py
+++ b/src/leap/bitmask/platform_init/initializers.py
@@ -482,7 +482,7 @@ def _linux_install_missing_scripts(badexec, notfound):
"""
success = False
installer_path = os.path.abspath(
- os.path.join(os.getcwd(), "apps", "eip", "files"))
+ os.path.join(os.getcwd(), "..", "apps", "eip", "files"))
install_helper = "leap-install-helper.sh"
install_helper_path = os.path.join(installer_path, install_helper)
--
cgit v1.2.3
From b8acf1a9df87945012387dced43f8de5e13164a0 Mon Sep 17 00:00:00 2001
From: Kali Kaneko
Date: Wed, 6 Apr 2016 16:11:14 -0400
Subject: [style] autopep8
---
src/leap/bitmask/platform_init/initializers.py | 34 +++++++++++++-------------
1 file changed, 17 insertions(+), 17 deletions(-)
diff --git a/src/leap/bitmask/platform_init/initializers.py b/src/leap/bitmask/platform_init/initializers.py
index f0ec2d53..193bd80a 100644
--- a/src/leap/bitmask/platform_init/initializers.py
+++ b/src/leap/bitmask/platform_init/initializers.py
@@ -440,29 +440,29 @@ def _get_missing_complain_dialog(stuff):
class ComplainDialog(QtGui.QDialog):
def __init__(self, parent=None):
- super(ComplainDialog, self).__init__(parent)
+ super(ComplainDialog, self).__init__(parent)
- label = QtGui.QLabel(msgstr.NO_HELPERS)
- label.setAlignment(QtCore.Qt.AlignLeft)
+ label = QtGui.QLabel(msgstr.NO_HELPERS)
+ label.setAlignment(QtCore.Qt.AlignLeft)
- label2 = QtGui.QLabel(msgstr.EXPLAIN)
- label2.setAlignment(QtCore.Qt.AlignLeft)
+ label2 = QtGui.QLabel(msgstr.EXPLAIN)
+ label2.setAlignment(QtCore.Qt.AlignLeft)
- textedit = QtGui.QTextEdit()
- textedit.setText("\n".join(stuff))
+ textedit = QtGui.QTextEdit()
+ textedit.setText("\n".join(stuff))
- ok = QtGui.QPushButton()
- ok.setText(self.tr("Ok, thanks"))
- self.ok = ok
- self.ok.clicked.connect(self.close)
+ ok = QtGui.QPushButton()
+ ok.setText(self.tr("Ok, thanks"))
+ self.ok = ok
+ self.ok.clicked.connect(self.close)
- mainLayout = QtGui.QGridLayout()
- mainLayout.addWidget(label, 0, 0)
- mainLayout.addWidget(label2, 1, 0)
- mainLayout.addWidget(textedit, 2, 0)
- mainLayout.addWidget(ok, 3, 0)
+ mainLayout = QtGui.QGridLayout()
+ mainLayout.addWidget(label, 0, 0)
+ mainLayout.addWidget(label2, 1, 0)
+ mainLayout.addWidget(textedit, 2, 0)
+ mainLayout.addWidget(ok, 3, 0)
- self.setLayout(mainLayout)
+ self.setLayout(mainLayout)
msg = ComplainDialog()
msg.setWindowTitle(msg.tr("Missing Bitmask helper files"))
--
cgit v1.2.3
From dadfb03b90d099d50c7c225da297952cdfb7b9aa Mon Sep 17 00:00:00 2001
From: Kali Kaneko
Date: Thu, 7 Apr 2016 10:47:56 -0400
Subject: [docs] fix config path reflecting bundle change
---
pkg/PixelatedWebmail.README | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/pkg/PixelatedWebmail.README b/pkg/PixelatedWebmail.README
index c45dc9ae..06e52964 100644
--- a/pkg/PixelatedWebmail.README
+++ b/pkg/PixelatedWebmail.README
@@ -15,7 +15,7 @@ account with a mail-enabled provider (for instance, mail.bitmask.net).
Then, you have to edit a config file living inside the bundle folders. You have
to add "Pixmail=true" under the [General] section, like this:
-config/leap/leap.conf:
+lib/config/leap/leap.conf:
[General]
SkipFirstRun=true
--
cgit v1.2.3
From 42e4458f3f37d50725a37a7e22835ab677cc24aa Mon Sep 17 00:00:00 2001
From: Kali Kaneko
Date: Thu, 7 Apr 2016 11:09:05 -0400
Subject: [style] pep8
---
setup.py | 39 ++++++++++++++++----------------
src/leap/bitmask/__init__.py | 3 ++-
src/leap/bitmask/app.py | 20 ++++++++--------
src/leap/bitmask/config/leapsettings.py | 1 -
src/leap/bitmask/util/keyring_helpers.py | 5 ++--
src/leap/bitmask/util/pastebin.py | 4 ++--
6 files changed, 37 insertions(+), 35 deletions(-)
diff --git a/setup.py b/setup.py
index 5bf5d186..62e9b115 100755
--- a/setup.py
+++ b/setup.py
@@ -20,37 +20,43 @@ Setup file for bitmask.
"""
from __future__ import print_function
+import glob
import hashlib
-import sys
import os
+import platform
import re
+import shutil
+import sys
from distutils.command.build import build as _build
from setuptools import Command
+from setuptools.command.develop import develop as _develop
-if not sys.version_info[0] == 2:
- print("[ERROR] Sorry, Python 3 is not supported (yet). "
- "Try running with python2: python2 setup.py ...")
- exit()
-
-try:
- from setuptools import setup, find_packages
-except ImportError:
- from pkg import distribute_setup
- distribute_setup.use_setuptools()
- from setuptools import setup, find_packages
from pkg import utils
import versioneer
-
# The following import avoids the premature unloading of the `util` submodule
# when running tests, which would cause an error when nose finishes tests and
# calls the exit function of the multiprocessing module.
from multiprocessing import util
assert(util)
+
+try:
+ from setuptools import setup, find_packages
+except ImportError:
+ from pkg import distribute_setup
+ distribute_setup.use_setuptools()
+ from setuptools import setup, find_packages
+
+if not sys.version_info[0] == 2:
+ print("[ERROR] Sorry, Python 3 is not supported (yet). "
+ "Try running with python2: python2 setup.py ...")
+ exit()
+
+
setup_root = os.path.dirname(__file__)
sys.path.insert(0, os.path.join(setup_root, "src"))
@@ -167,8 +173,6 @@ else:
leap_launcher = 'bitmask=leap.bitmask.app:start_app'
-from setuptools.command.develop import develop as _develop
-
def copy_reqs(path, withsrc=False):
# add a copy of the processed requirements to the package
@@ -365,10 +369,6 @@ class cmd_sdist(versioneer_sdist):
pass
-import shutil
-import glob
-
-
def _get_leap_versions():
versions = {}
with open("pkg/leap_versions.txt") as vf:
@@ -457,7 +457,6 @@ def copy_recursively(source_folder, destination_folder):
cmdclass["build"] = cmd_build
cmdclass["sdist"] = cmd_sdist
-import platform
_system = platform.system()
IS_LINUX = _system == "Linux"
IS_MAC = _system == "Darwin"
diff --git a/src/leap/bitmask/__init__.py b/src/leap/bitmask/__init__.py
index 6ab55e53..c25ae999 100644
--- a/src/leap/bitmask/__init__.py
+++ b/src/leap/bitmask/__init__.py
@@ -19,6 +19,8 @@ Init file for leap.bitmask
Initializes version and app info.
"""
+from ._version import get_versions
+
# HACK: This is a hack so that py2app copies _scrypt.so to the right
# place, it can't be technically imported, but that doesn't matter
# because the import is never executed
@@ -45,7 +47,6 @@ def _is_release_version(version_str):
return patch.isdigit()
-from ._version import get_versions
__version__ = get_versions()['version']
__version_hash__ = get_versions()['full-revisionid']
IS_RELEASE_VERSION = _is_release_version(__version__)
diff --git a/src/leap/bitmask/app.py b/src/leap/bitmask/app.py
index 0c4c32e2..0ae60e48 100644
--- a/src/leap/bitmask/app.py
+++ b/src/leap/bitmask/app.py
@@ -46,11 +46,7 @@ import os
import platform
import sys
-if platform.system() == "Darwin":
- # We need to tune maximum number of files, due to zmq usage
- # we hit the limit.
- import resource
- resource.setrlimit(resource.RLIMIT_NOFILE, (4096, 10240))
+import psutil
from leap.bitmask import __version__ as VERSION
from leap.bitmask.backend.backend_proxy import BackendProxy
@@ -70,7 +66,12 @@ from leap.mail import __version__ as MAIL_VERSION
import codecs
codecs.register(lambda name: codecs.lookup('utf-8')
if name == 'cp65001' else None)
-import psutil
+
+if platform.system() == "Darwin":
+ # We need to tune maximum number of files, due to zmq usage
+ # we hit the limit.
+ import resource
+ resource.setrlimit(resource.RLIMIT_NOFILE, (4096, 10240))
def kill_the_children():
@@ -226,9 +227,10 @@ def start_app():
backend_pid = None
if not backend_running:
frontend_pid = os.getpid()
- backend_process = multiprocessing.Process(target=run_backend,
- name='Backend',
- args=(opts.danger, flags_dict, frontend_pid))
+ backend_process = multiprocessing.Process(
+ target=run_backend,
+ name='Backend',
+ args=(opts.danger, flags_dict, frontend_pid))
# we don't set the 'daemon mode' since we need to start child processes
# in the backend
# backend_process.daemon = True
diff --git a/src/leap/bitmask/config/leapsettings.py b/src/leap/bitmask/config/leapsettings.py
index d7590c24..01900484 100644
--- a/src/leap/bitmask/config/leapsettings.py
+++ b/src/leap/bitmask/config/leapsettings.py
@@ -361,4 +361,3 @@ class LeapSettings(object):
def set_pixelmail_enabled(self, enabled):
leap_assert_type(enabled, bool)
self._settings.setvalue(self.PIXELMAIL_KEY, enabled)
-
diff --git a/src/leap/bitmask/util/keyring_helpers.py b/src/leap/bitmask/util/keyring_helpers.py
index d81f39b1..c5181348 100644
--- a/src/leap/bitmask/util/keyring_helpers.py
+++ b/src/leap/bitmask/util/keyring_helpers.py
@@ -24,8 +24,9 @@ try:
EncryptedKeyring,
PlaintextKeyring
]
- canuse = lambda kr: (kr is not None
- and kr.__class__ not in OBSOLETE_KEYRINGS)
+ canuse = lambda kr: (
+ kr is not None and
+ kr.__class__ not in OBSOLETE_KEYRINGS)
except Exception:
# Problems when importing keyring! It might be a problem binding to the
diff --git a/src/leap/bitmask/util/pastebin.py b/src/leap/bitmask/util/pastebin.py
index 6d50ac9e..b476ad88 100644
--- a/src/leap/bitmask/util/pastebin.py
+++ b/src/leap/bitmask/util/pastebin.py
@@ -25,13 +25,13 @@
#############################################################################
+import urllib
+
__ALL__ = ['delete_paste', 'user_details', 'trending', 'pastes_by_user',
'generate_user_key', 'paste', 'Pastebin', 'PastebinError',
'PostLimitError']
-import urllib
-
class PastebinError(RuntimeError):
"""Pastebin API error.
--
cgit v1.2.3
From 3340e1a898bacdd05fb6e6bf8d37596f7aff81a2 Mon Sep 17 00:00:00 2001
From: Kali Kaneko
Date: Thu, 7 Apr 2016 09:56:36 -0400
Subject: [feat] use same token for imap/smtp authentication
This greatly simplifies the handling of the password in the thunderbird
extension.
- Related: #6041
---
src/leap/bitmask/backend/components.py | 7 ++-----
src/leap/bitmask/gui/mainwindow.py | 14 ++++++--------
2 files changed, 8 insertions(+), 13 deletions(-)
diff --git a/src/leap/bitmask/backend/components.py b/src/leap/bitmask/backend/components.py
index 0c2b3280..f9ad1480 100644
--- a/src/leap/bitmask/backend/components.py
+++ b/src/leap/bitmask/backend/components.py
@@ -806,11 +806,8 @@ class Soledad(object):
(service, token))
sol = self._soledad_bootstrapper.soledad
- d = sol.get_or_create_service_token('imap')
- d.addCallback(register_service_token, 'imap')
- d.addCallback(
- lambda _: sol.get_or_create_service_token('smtp'))
- d.addCallback(register_service_token, 'smtp')
+ d = sol.get_or_create_service_token('mail_auth')
+ d.addCallback(register_service_token, 'mail_auth')
d.addCallback(lambda _: result)
return d
diff --git a/src/leap/bitmask/gui/mainwindow.py b/src/leap/bitmask/gui/mainwindow.py
index 839aae87..ace3f863 100644
--- a/src/leap/bitmask/gui/mainwindow.py
+++ b/src/leap/bitmask/gui/mainwindow.py
@@ -1089,12 +1089,11 @@ class MainWindow(QtGui.QMainWindow, SignalTracker):
# FIXME on i3, this doens't allow to mouse-select.
# Switch to a dialog in which we can set the QLabel
- imap_token = (self._service_tokens.get('imap', None) or
- "??? (log in to unlock)")
- smtp_token = (self._service_tokens.get('smtp', None) or
- "??? (log in to unlock)")
- imap_password = self.tr("IMAP Password:") + " %s" % (imap_token,)
- smtp_password = self.tr("SMTP Password:") + " %s" % (smtp_token,)
+ mail_auth_token = (
+ self._service_tokens.get('mail_auth', None) or
+ "??? (log in to unlock)")
+ mail_password = self.tr("IMAP/SMTP Password:") + " %s" % (
+ mail_auth_token,)
msg = help_url + self.tr(
"
{0}
"
@@ -1105,10 +1104,9 @@ class MainWindow(QtGui.QMainWindow, SignalTracker):
"
{4}
"
"
{5}
"
"
{6}
"
- "
{7}
"
"").format(email_quick_reference, thunderbird_text,
manual_text, manual_imap, manual_smtp,
- manual_username, imap_password, smtp_password)
+ manual_username, mail_password)
QtGui.QMessageBox.about(self, self.tr("Bitmask Help"), msg)
def _needs_update(self):
--
cgit v1.2.3
From 939fefc012213d3aa433caec47e2e0b19d64901e Mon Sep 17 00:00:00 2001
From: Ruben Pollan
Date: Wed, 30 Mar 2016 13:51:01 +0200
Subject: [feat] Write service tokens to a file
The thunderbird plugin will read the tokens from there.
- Related: #6041
---
changes/next-changelog.rst | 1 +
src/leap/bitmask/backend/components.py | 22 ++++++++++++++++++++++
2 files changed, 23 insertions(+)
diff --git a/changes/next-changelog.rst b/changes/next-changelog.rst
index b20efdc8..3240d2bb 100644
--- a/changes/next-changelog.rst
+++ b/changes/next-changelog.rst
@@ -13,6 +13,7 @@ Features
- `#7552 `_: Improve UI message and add some margin above the msg box.
- `#7656 `_: Adapt to multi-user aware events.
- `#4469 `_: Display randomly generated service token on the Help Window.
+- `#6041 `_: Write service tokens to a file to allow email clients to read them from there.
- Use cred-based authentication on SMTP.
- Experimental support for the Pixelated WebMail.
diff --git a/src/leap/bitmask/backend/components.py b/src/leap/bitmask/backend/components.py
index f9ad1480..bc34c84c 100644
--- a/src/leap/bitmask/backend/components.py
+++ b/src/leap/bitmask/backend/components.py
@@ -20,8 +20,11 @@ Backend components
# TODO [ ] Get rid of all this deferToThread mess, or at least contain
# all of it into its own threadpool.
+import json
import os
+import shutil
import socket
+import tempfile
import time
from functools import partial
@@ -789,6 +792,8 @@ class Soledad(object):
download_if_needed=True)
self._soledad_defer.addCallback(self._set_proxies_cb)
self._soledad_defer.addCallback(self._set_service_tokens_cb)
+ self._soledad_defer.addCallback(self._write_tokens_file,
+ username, domain)
else:
if self._signaler is not None:
self._signaler.signal(self._signaler.soledad_bootstrap_failed)
@@ -811,6 +816,23 @@ class Soledad(object):
d.addCallback(lambda _: result)
return d
+ def _write_tokens_file(self, result, username, domain):
+ tokens_folder = os.path.join(tempfile.gettempdir(), "bitmask_tokens")
+ if os.path.exists(tokens_folder):
+ try:
+ shutil.rmtree(tokens_folder)
+ except OSError as e:
+ logger.error("Can't remove tokens folder %s: %s"
+ % (tokens_folder, e))
+ return
+ os.mkdir(tokens_folder, 0700)
+
+ tokens_path = os.path.join(tokens_folder,
+ "%s@%s.json" % (username, domain))
+ with open(tokens_path, 'w') as ftokens:
+ json.dump(self._service_tokens, ftokens)
+ return result
+
def _set_proxies_cb(self, _):
"""
Update the soledad and keymanager proxies to reference the ones created
--
cgit v1.2.3
From 130f1a8753bfe63f5575fc2011a15af9a0752170 Mon Sep 17 00:00:00 2001
From: Kali Kaneko
Date: Thu, 7 Apr 2016 12:18:24 -0400
Subject: [bug] allow resizing browser window
---
src/leap/bitmask/gui/mainwindow.py | 1 +
src/leap/bitmask/gui/qt_browser.py | 14 ++++++++++----
2 files changed, 11 insertions(+), 4 deletions(-)
diff --git a/src/leap/bitmask/gui/mainwindow.py b/src/leap/bitmask/gui/mainwindow.py
index ace3f863..168de8ed 100644
--- a/src/leap/bitmask/gui/mainwindow.py
+++ b/src/leap/bitmask/gui/mainwindow.py
@@ -579,6 +579,7 @@ class MainWindow(QtGui.QMainWindow, SignalTracker):
def _show_pixelated_browser(self):
win = PixelatedWindow(self)
win.show()
+ win.load_app()
def _update_eip_enabled_status(self, account=None, services=None):
"""
diff --git a/src/leap/bitmask/gui/qt_browser.py b/src/leap/bitmask/gui/qt_browser.py
index e480b363..b75bfb64 100644
--- a/src/leap/bitmask/gui/qt_browser.py
+++ b/src/leap/bitmask/gui/qt_browser.py
@@ -26,8 +26,14 @@ PIXELATED_URI = 'http://localhost:9090'
class PixelatedWindow(QtGui.QDialog):
def __init__(self, parent):
- QtGui.QDialog.__init__(self, parent)
- self.web = QtWebKit.QWebView(self)
- self.web.load(QtCore.QUrl(PIXELATED_URI))
+ super(PixelatedWindow, self).__init__(parent)
+ self.view = QtWebKit.QWebView(self)
+
+ layout = QtGui.QGridLayout()
+ layout.setContentsMargins(0, 0, 0, 0)
+ layout.addWidget(self.view)
+ self.setLayout(layout)
self.setWindowTitle('Bitmask/Pixelated WebMail')
- self.web.show()
+
+ def load_app(self):
+ self.view.load(QtCore.QUrl(PIXELATED_URI))
--
cgit v1.2.3
From fcb9513a8df9b2d690607106d3397b7c785f3b33 Mon Sep 17 00:00:00 2001
From: Kali Kaneko
Date: Fri, 8 Apr 2016 01:08:53 -0400
Subject: [bug] fix pixelated-www path
---
src/leap/bitmask/pix.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/leap/bitmask/pix.py b/src/leap/bitmask/pix.py
index a05a1d9c..aa18c589 100644
--- a/src/leap/bitmask/pix.py
+++ b/src/leap/bitmask/pix.py
@@ -61,7 +61,7 @@ def start_pixelated_user_agent(userid, soledad, keymanager):
# we are running in a |PyInstaller| bundle
static_folder = os.path.join(sys._MEIPASS, 'pixelated_www')
else:
- static_folder = os.path.abspath(pixelated_www.__path__)
+ static_folder = os.path.abspath(pixelated_www.__path__[0])
resource = RootResource(services_factory, static_folder=static_folder)
--
cgit v1.2.3
From 977f594510b70c7f0d1c99d1d77c188ff6ba8e37 Mon Sep 17 00:00:00 2001
From: Kali Kaneko
Date: Mon, 11 Apr 2016 17:47:50 -0400
Subject: [bug] workaround for qt gui corruption in wily
- Resolves: #8028
---
src/leap/bitmask/app.py | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/src/leap/bitmask/app.py b/src/leap/bitmask/app.py
index 0ae60e48..2c41068c 100644
--- a/src/leap/bitmask/app.py
+++ b/src/leap/bitmask/app.py
@@ -74,6 +74,11 @@ if platform.system() == "Darwin":
resource.setrlimit(resource.RLIMIT_NOFILE, (4096, 10240))
+def qt_hack_ubuntu():
+ """Export an env var to avoid gui corruption, see #8028"""
+ os.environ['QT_GRAPHICSSYSTEM'] = 'native'
+
+
def kill_the_children():
"""
Make sure no lingering subprocesses are left in case of a bad termination.
@@ -151,6 +156,8 @@ def start_app():
"""
Starts the main event loop and launches the main window.
"""
+ qt_hack_ubuntu()
+
# Ignore the signals since we handle them in the subprocesses
# signal.signal(signal.SIGINT, signal.SIG_IGN)
--
cgit v1.2.3
From 5fc9a8c68216bcdd7a4d847e75bac428aafda5e4 Mon Sep 17 00:00:00 2001
From: Kali Kaneko
Date: Mon, 11 Apr 2016 17:49:01 -0400
Subject: [bug] hash the installed binaries
this was the cause for the previous alpha releases keep insisting on
re-installing the helper files.
- Resolves: #7989
- Releases: 0.9.2
---
pkg/next-version | 2 +-
pkg/pyinst/pyinst-build.mk | 6 +++++-
setup.py | 1 +
3 files changed, 7 insertions(+), 2 deletions(-)
diff --git a/pkg/next-version b/pkg/next-version
index 8df8fe62..1c3e8a50 100644
--- a/pkg/next-version
+++ b/pkg/next-version
@@ -1 +1 @@
-0.9.2.alpha3
+0.9.2.alpha4
diff --git a/pkg/pyinst/pyinst-build.mk b/pkg/pyinst/pyinst-build.mk
index 16737ead..348395cc 100644
--- a/pkg/pyinst/pyinst-build.mk
+++ b/pkg/pyinst/pyinst-build.mk
@@ -3,7 +3,11 @@ freeze-ver:
sed -i 's/^version_version\(.*\)/version_version = "$(NEXT_VERSION)"/' src/leap/bitmask/_version.py
sed -i 's/^full_revisionid\(.*\)/full_revisionid = "$(GIT_COMMIT)"/' src/leap/bitmask/_version.py
-pyinst: freeze-ver
+hash-binaries:
+ # TODO get from a build dir
+ OPENVPN_BIN=/usr/sbin/openvpn BITMASK_ROOT=pkg/linux/bitmask-root python setup.py hash_binaries
+
+pyinst: freeze-ver hash-binaries
pyinstaller -y pkg/pyinst/bitmask.spec
reset-ver:
diff --git a/setup.py b/setup.py
index 62e9b115..8dc5a694 100755
--- a/setup.py
+++ b/setup.py
@@ -219,6 +219,7 @@ class cmd_binary_hash(Command):
pass
def run(self, *args):
+ # TODO check gnupg binary too.
OPENVPN_BIN = os.environ.get('OPENVPN_BIN', None)
BITMASK_ROOT = os.environ.get('BITMASK_ROOT', None)
--
cgit v1.2.3
From f05ec77ae21f8b01f20267c129307c91683c74d7 Mon Sep 17 00:00:00 2001
From: Kali Kaneko
Date: Mon, 11 Apr 2016 17:55:19 -0400
Subject: [pkg] remove wrapper hacks, not needed anymore
---
pkg/pyinst/pyinst-build.mk | 13 -------------
1 file changed, 13 deletions(-)
diff --git a/pkg/pyinst/pyinst-build.mk b/pkg/pyinst/pyinst-build.mk
index 348395cc..cbbef198 100644
--- a/pkg/pyinst/pyinst-build.mk
+++ b/pkg/pyinst/pyinst-build.mk
@@ -29,18 +29,6 @@ pyinst-trim:
#rm -f dist/bitmask/libgstaudio0.0.so.0
#rm -f dist/bitmask/libgstreamer-1.0.so.0
-pyinst-wrapper:
- # TODO this *is* an ugly hack, See #7352
- mv $(DIST)libQtCore.so.4 $(DIST)libQtCore.so.4.orig
- mv $(DIST)libQtGui.so.4 $(DIST)libQtGui.so.4.orig
- mv $(DIST)libQtNetwork.so.4 $(DIST)libQtNetwork.so.4.orig
- mv $(DIST)libQtSvg.so.4 $(DIST)libQtSvg.so.4.orig
- mv $(DIST)libQtWebKit.so.4 $(DIST)libQtWebKit.so.4.orig
- mv $(DIST)libQtXmlPatterns.so.4 $(DIST)libQtXmlPatterns.so.4.orig
- mv $(DIST)libQtXml.so.4 $(DIST)libQtXml.so.4.orig
- mv $(DIST)bitmask $(DIST)bitmask-app
- cp pkg/linux/bitmask-launcher $(DIST)bitmask
-
pyinst-cleanup:
rm -rf $(DIST)config
mkdir -p $(DIST_VERSION)
@@ -73,7 +61,6 @@ pyinst-sign:
pyinst-upload:
scp dist/Bitmask.$(NEXT_VERSION).* salmon.leap.se:./
-#pyinst-linux: pyinst pyinst-hacks pyinst-trim pyinst-wrapper pyinst-cleanup pyinst-distribution-data pyinst-tar
pyinst-linux: pyinst reset-ver pyinst-hacks pyinst-trim pyinst-cleanup pyinst-distribution-data pyinst-linux-helpers pyinst-tar
clean_pkg:
--
cgit v1.2.3
From ed7c2bdf2efc2ce4e0ef4d761d9470604efa9969 Mon Sep 17 00:00:00 2001
From: Kali Kaneko
Date: Mon, 11 Apr 2016 18:01:42 -0400
Subject: [docs] add some important info about building bundles
---
pkg/pyinst/README.rst | 17 +++++++++++++++++
1 file changed, 17 insertions(+)
create mode 100644 pkg/pyinst/README.rst
diff --git a/pkg/pyinst/README.rst b/pkg/pyinst/README.rst
new file mode 100644
index 00000000..b6784a52
--- /dev/null
+++ b/pkg/pyinst/README.rst
@@ -0,0 +1,17 @@
+Building da bundles
+--------------------
+Because, you know, bundles are cool. Who needs a decent package manager nowadays? .
+
+You need a couple of things in your virtualenv:
+
+- All the dependencies. A sumo tarball is probably a good idea.
+- PyInstaller. Version 3 or higher.
+- A PySide build. While the postmkenv.sh hack is good enough for
+ developing, you will need a wheel built with --standalone flag.
+ See
+ http://pyside.readthedocs.org/en/latest/building/linux.html#building-pyside-distribution::
+
+ $ python2.7 setup.py bdist_wheel --qmake=/usr/bin/qmake-qt4 --standalone
+
+ (since this takes a while, you can probably grab the already built wheel from
+ the leap servers).
--
cgit v1.2.3
From 42bb82b06ea313877023da9f689782b228fac345 Mon Sep 17 00:00:00 2001
From: Kali Kaneko
Date: Wed, 13 Apr 2016 11:03:20 -0400
Subject: [feat] Adapt to latest pixelated-ua
In the latest snapshots, pixelated has migrated to use Account instead
of IMAPAccount.
Also, created an adaptor for Nicknym that allows to be initialized with
just the userid and the keymanager instance. This is ugly and has to go
when we converge on a single codebase (bitmask.core, hopefully).
---
src/leap/bitmask/pix.py | 56 ++++++++++++++++++++++++++++++++++++++-----------
1 file changed, 44 insertions(+), 12 deletions(-)
diff --git a/src/leap/bitmask/pix.py b/src/leap/bitmask/pix.py
index aa18c589..8d7d0811 100644
--- a/src/leap/bitmask/pix.py
+++ b/src/leap/bitmask/pix.py
@@ -25,11 +25,10 @@ from twisted.internet import defer
from twisted.python import log
from leap.bitmask.util import get_path_prefix
-from leap.mail.imap.account import IMAPAccount
+from leap.mail.mail import Account
+from leap.keymanager import openpgp, KeyNotFound
try:
- import pixelated_www
-
from pixelated.adapter.mailstore import LeapMailStore
from pixelated.adapter.welcome_mail import add_welcome_mail
from pixelated.application import SingleUserServicesFactory
@@ -39,6 +38,7 @@ try:
from pixelated.bitmask_libraries.session import SessionCache
from pixelated.config import services
from pixelated.resources.root_resource import RootResource
+ import pixelated_www
HAS_PIXELATED = True
except ImportError:
HAS_PIXELATED = False
@@ -70,10 +70,11 @@ def start_pixelated_user_agent(userid, soledad, keymanager):
config.sslkey = None
config.sslcert = None
- deferred = _start_in_single_user_mode(
- leap_session, config,
- resource, services_factory)
- return deferred
+ d = leap_session.account.callWhenReady(
+ lambda _: _start_in_single_user_mode(
+ leap_session, config,
+ resource, services_factory))
+ return d
def get_smtp_config(provider):
@@ -90,6 +91,39 @@ def get_smtp_config(provider):
return config
+class NickNym(object):
+
+ def __init__(self, keymanager, userid):
+ self._email = userid
+ self.keymanager = keymanager
+
+ @defer.inlineCallbacks
+ def generate_openpgp_key(self):
+ key_present = yield self._key_exists(self._email)
+ if not key_present:
+ yield self._gen_key()
+ yield self._send_key_to_leap()
+
+ @defer.inlineCallbacks
+ def _key_exists(self, email):
+ try:
+ yield self.fetch_key(email, private=True, fetch_remote=False)
+ defer.returnValue(True)
+ except KeyNotFound:
+ defer.returnValue(False)
+
+ def fetch_key(self, email, private=False, fetch_remote=True):
+ return self.keymanager.get_key(
+ email, openpgp.OpenPGPKey,
+ private=private, fetch_remote=fetch_remote)
+
+ def _gen_key(self):
+ return self.keymanager.gen_key(openpgp.OpenPGPKey)
+
+ def _send_key_to_leap(self):
+ return self.keymanager.send_key(openpgp.OpenPGPKey)
+
+
class LeapSessionAdapter(object):
def __init__(self, userid, soledad, keymanager):
@@ -97,10 +131,8 @@ class LeapSessionAdapter(object):
self.soledad = soledad
- # FIXME this expects a keymanager-like instance
- self.nicknym = Config()
- self.nicknym.keymanager = keymanager
-
+ # XXX this needs to be converged with our public apis.
+ self.nicknym = NickNym(keymanager, userid)
self.mail_store = LeapMailStore(soledad)
self.user_auth = Config()
@@ -108,7 +140,7 @@ class LeapSessionAdapter(object):
self.fresh_account = False
self.incoming_mail_fetcher = None
- self.account = IMAPAccount(userid, soledad, defer.Deferred())
+ self.account = Account(soledad)
username, provider = userid.split('@')
smtp_client_cert = os.path.join(
--
cgit v1.2.3
From 6c91aee9c3a0978a7019f3fdf52f4209977b5f0b Mon Sep 17 00:00:00 2001
From: Kali Kaneko
Date: Wed, 13 Apr 2016 12:00:36 -0400
Subject: [feature] make branding-logo: patches pixelated app logo
and replaces it with bitmask-logo.svg
- Releases: 0.9.2
---
Makefile | 1 +
pkg/branding/bitmask-logo.svg | 19 ++++++++++++++
pkg/branding/branding.mk | 2 ++
pkg/branding/patch_pixel_logo.py | 57 ++++++++++++++++++++++++++++++++++++++++
4 files changed, 79 insertions(+)
create mode 100644 pkg/branding/bitmask-logo.svg
create mode 100644 pkg/branding/branding.mk
create mode 100644 pkg/branding/patch_pixel_logo.py
diff --git a/Makefile b/Makefile
index f96d810d..8e275e93 100644
--- a/Makefile
+++ b/Makefile
@@ -147,6 +147,7 @@ checkout_leapdeps_develop:
include pkg/sumo-tarballs.mk
include pkg/pyinst/pyinst-build.mk
+include pkg/branding/branding.mk
clean :
$(RM) $(COMPILED_UI) $(COMPILED_RESOURCES) $(COMPILED_UI:.py=.pyc) $(COMPILED_RESOURCES:.py=.pyc)
diff --git a/pkg/branding/bitmask-logo.svg b/pkg/branding/bitmask-logo.svg
new file mode 100644
index 00000000..0eccc057
--- /dev/null
+++ b/pkg/branding/bitmask-logo.svg
@@ -0,0 +1,19 @@
+
+
\ No newline at end of file
diff --git a/pkg/branding/branding.mk b/pkg/branding/branding.mk
new file mode 100644
index 00000000..6b98d40d
--- /dev/null
+++ b/pkg/branding/branding.mk
@@ -0,0 +1,2 @@
+branding-logo:
+ python pkg/branding/patch_pixel_logo.py
diff --git a/pkg/branding/patch_pixel_logo.py b/pkg/branding/patch_pixel_logo.py
new file mode 100644
index 00000000..464bb729
--- /dev/null
+++ b/pkg/branding/patch_pixel_logo.py
@@ -0,0 +1,57 @@
+# -*- coding: utf-8 -*-
+# patch_pixelated_logo.py
+# Copyright (C) 2016 LEAP Encryption Acess Project
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see .
+"""
+Patch the Pixelated Logo in the index.html, replacing it with a rebranded
+Bitmask Logo. To be used in the pixelated_www assets distributed with the
+Bitmask bundles.
+"""
+__author__ = 'Kali Kaneko '
+
+import os
+import sys
+
+from BeautifulSoup import BeautifulSoup
+
+
+def patch_logo(orig_path, replacement_path):
+
+ with open(orig_path, 'r') as of:
+ orig = BeautifulSoup(of.read())
+
+ with open(replacement_path, 'r') as rf:
+ new = BeautifulSoup(rf.read())
+
+ new_svg = new.find('svg')
+ old_svg = orig.find('svg')
+ old_svg.replaceWith(new_svg)
+
+ with open(orig_path, 'w') as f:
+ f.write(str(orig))
+
+
+if __name__ == "__main__":
+ here = os.path.dirname(os.path.realpath(__file__))
+ if len(sys.argv) > 1:
+ orig_path = sys.argv[1]
+ else:
+ import pixelated_www
+ orig_path = os.path.join(pixelated_www.__path__[0],
+ 'index.html')
+ assert os.path.isfile(orig_path)
+ new_path = os.path.join(here, 'bitmask-logo.svg')
+ print('>>> patching file %s with logo in %s' % (orig_path, new_path))
+ patch_logo(orig_path, new_path)
--
cgit v1.2.3
From 054e337ecf18e0a3ddd1d5568bfbdef507a3d136 Mon Sep 17 00:00:00 2001
From: Kali Kaneko
Date: Thu, 14 Apr 2016 15:37:14 -0400
Subject: [bug] add missing assets for pixelated
---
pkg/pyinst/pyinst-build.mk | 2 ++
1 file changed, 2 insertions(+)
diff --git a/pkg/pyinst/pyinst-build.mk b/pkg/pyinst/pyinst-build.mk
index cbbef198..2c2fe45a 100644
--- a/pkg/pyinst/pyinst-build.mk
+++ b/pkg/pyinst/pyinst-build.mk
@@ -16,8 +16,10 @@ reset-ver:
pyinst-hacks:
cp ../leap_common/src/leap/common/cacert.pem $(DIST)
mkdir -p $(DIST)pysqlcipher
+ mkdir -p $(DIST)pixelated
cp $(VIRTUAL_ENV)/lib/python2.7/site-packages/pysqlcipher/_sqlite.so $(DIST)pysqlcipher
cp -r $(VIRTUAL_ENV)/lib/python2.7/site-packages/pixelated_www $(DIST)
+ cp -r $(VIRTUAL_ENV)/lib/python2.7/site-packages/pixelated/assets/ $(DIST)pixelated
pyinst-trim:
rm -f $(DIST)libQtOpenGL.so.4
--
cgit v1.2.3
From b4de087fee85b7831b70cde31e7ed34f196a5ca9 Mon Sep 17 00:00:00 2001
From: Kali Kaneko
Date: Thu, 14 Apr 2016 15:38:39 -0400
Subject: [bug] add twisted.web.failure.xhtml
---
pkg/pyinst/pyinst-build.mk | 2 ++
1 file changed, 2 insertions(+)
diff --git a/pkg/pyinst/pyinst-build.mk b/pkg/pyinst/pyinst-build.mk
index 2c2fe45a..b6a7a6f3 100644
--- a/pkg/pyinst/pyinst-build.mk
+++ b/pkg/pyinst/pyinst-build.mk
@@ -17,9 +17,11 @@ pyinst-hacks:
cp ../leap_common/src/leap/common/cacert.pem $(DIST)
mkdir -p $(DIST)pysqlcipher
mkdir -p $(DIST)pixelated
+ mkdir -p $(DIST)twisted/web
cp $(VIRTUAL_ENV)/lib/python2.7/site-packages/pysqlcipher/_sqlite.so $(DIST)pysqlcipher
cp -r $(VIRTUAL_ENV)/lib/python2.7/site-packages/pixelated_www $(DIST)
cp -r $(VIRTUAL_ENV)/lib/python2.7/site-packages/pixelated/assets/ $(DIST)pixelated
+ cp -r $(VIRTUAL_ENV)/lib/python2.7/site-packages/twisted/web/failure.xhtml $(DIST)twisted/web/
pyinst-trim:
rm -f $(DIST)libQtOpenGL.so.4
--
cgit v1.2.3
From c201029c3070da1bd9c2a7d65ac426e49f3cc241 Mon Sep 17 00:00:00 2001
From: Kali Kaneko
Date: Thu, 14 Apr 2016 15:40:05 -0400
Subject: [pkg] ship statically built binaries
- mention the versions in the next relnotes
- add the leap_thirdparty_build to gitignore.
the build scripts are supposed to place the binaries here.
---
.gitignore | 1 +
Makefile | 1 +
pkg/pyinst/pyinst-build.mk | 9 +++------
release-notes.rst | 19 +++++++++----------
4 files changed, 14 insertions(+), 16 deletions(-)
diff --git a/.gitignore b/.gitignore
index 62b21fd1..35c5d4a9 100644
--- a/.gitignore
+++ b/.gitignore
@@ -39,3 +39,4 @@ data/bitmask.pro
bitmask-resources.png
docker/data
+leap_thirdparty_build
diff --git a/Makefile b/Makefile
index 8e275e93..7d26a7ae 100644
--- a/Makefile
+++ b/Makefile
@@ -46,6 +46,7 @@ DIST = dist/bitmask/
NEXT_VERSION = $(shell cat pkg/next-version)
DIST_VERSION = dist/bitmask-$(NEXT_VERSION)/
GIT_COMMIT = $(shell git rev-parse HEAD)
+LEAP_BUILD_DIR = leap_thirdparty_build/
#################################
diff --git a/pkg/pyinst/pyinst-build.mk b/pkg/pyinst/pyinst-build.mk
index b6a7a6f3..9120e7a1 100644
--- a/pkg/pyinst/pyinst-build.mk
+++ b/pkg/pyinst/pyinst-build.mk
@@ -4,8 +4,7 @@ freeze-ver:
sed -i 's/^full_revisionid\(.*\)/full_revisionid = "$(GIT_COMMIT)"/' src/leap/bitmask/_version.py
hash-binaries:
- # TODO get from a build dir
- OPENVPN_BIN=/usr/sbin/openvpn BITMASK_ROOT=pkg/linux/bitmask-root python setup.py hash_binaries
+ OPENVPN_BIN=$(LEAP_BUILD_DIR)openvpn BITMASK_ROOT=pkg/linux/bitmask-root python setup.py hash_binaries
pyinst: freeze-ver hash-binaries
pyinstaller -y pkg/pyinst/bitmask.spec
@@ -47,14 +46,12 @@ pyinst-distribution-data:
pyinst-linux-helpers:
mkdir -p $(DIST_VERSION)apps/eip/files
- # TODO compile static
- cp /usr/sbin/openvpn $(DIST_VERSION)apps/eip/files/leap-openvpn
+ cp $(LEAP_BUILD_DIR)openvpn $(DIST_VERSION)apps/eip/files/leap-openvpn
cp pkg/linux/bitmask-root $(DIST_VERSION)apps/eip/files/
cp pkg/linux/leap-install-helper.sh $(DIST_VERSION)apps/eip/files/
cp pkg/linux/polkit/se.leap.bitmask.bundle.policy $(DIST_VERSION)apps/eip/files/
mkdir -p $(DIST_VERSION)apps/mail
- # TODO compile static
- cp /usr/bin/gpg $(DIST_VERSION)apps/mail
+ cp $(LEAP_BUILD_DIR)gpg $(DIST_VERSION)apps/mail
pyinst-tar:
cd dist/ && tar cvzf Bitmask.$(NEXT_VERSION).tar.gz bitmask-$(NEXT_VERSION)
diff --git a/release-notes.rst b/release-notes.rst
index 7a63901e..a9c0ff47 100644
--- a/release-notes.rst
+++ b/release-notes.rst
@@ -1,25 +1,24 @@
-0.9.1 November 03 - "the day of the calaca"
+0.9.2 April XY - "Panis et Circenses"
+++++++++++++++++++++++++++++++++++++++++++
-We were very pleased to announce Bitmask stable 0.9.1 :tada:.
+We were very pleased to announce Bitmask stable 0.9.2
This is a minor release and you can see changes on `the changelog`_.
-The complete list of things that have changed since 0.8.x series can be seen on
-`0.9.0 release notes`_
-Don't miss the big pile of changes we brought you on 0.9.0 :)
-
Using the latest Bitmask, Linux users will be able to use our encrypted email
-service, now in beta state! A Mac release is imminent and a windows release is
-underway.
+service, now in beta state! An alpha version for OSX is also available.
Currently we have a test provider for mail @ https://mail.bitmask.net This
provider is already bundled with Bitmask for easy access on the wizard. Please
help us test this and file bug reports here:
https://leap.se/code/projects/report-issues
+[Pixelated integration news]
+
+The standalone bundles for 0.9.2 include statically compiled binaries for
+OpenVPN 2.3.10 (compiled against PolarSSL 1.3.9) and GnuPG 1.4.20.
+
NOTE: beta means that we expect things not to break but we don't promise you
won't get any headaches or lose some email, so please be careful.
-.. _`the changelog`: https://github.com/leapcode/bitmask_client/blob/0.9.1/CHANGELOG.rst
-.. _`0.9.0 release notes`: https://github.com/leapcode/bitmask_client/blob/0.9.0/release-notes.rst
+.. _`the changelog`: https://github.com/leapcode/bitmask_client/blob/0.9.2/CHANGELOG.rst
--
cgit v1.2.3
From a6dca50aeded076fdac8548be0c8b94857301e01 Mon Sep 17 00:00:00 2001
From: Kali Kaneko
Date: Thu, 14 Apr 2016 16:04:22 -0400
Subject: [pkg] bump alpha version... closer to rc1!
---
pkg/next-version | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/pkg/next-version b/pkg/next-version
index 1c3e8a50..6e441158 100644
--- a/pkg/next-version
+++ b/pkg/next-version
@@ -1 +1 @@
-0.9.2.alpha4
+0.9.2.alpha5
--
cgit v1.2.3
From 6e2e5e08dca279b6ea4f7835415a3900c28dfd84 Mon Sep 17 00:00:00 2001
From: Kali Kaneko
Date: Thu, 14 Apr 2016 18:01:28 -0400
Subject: [bug] another workaround for the transparent window in wily
The previous "fix" attempt with QT_GRAPHICSSYSTEM=native apparently
wasn't fixing the issue consistently.
This extra env var works 100% of the times by my tests though.
- Resolves: #8028
---
pkg/next-version | 2 +-
src/leap/bitmask/app.py | 3 ++-
2 files changed, 3 insertions(+), 2 deletions(-)
diff --git a/pkg/next-version b/pkg/next-version
index 6e441158..e42c0587 100644
--- a/pkg/next-version
+++ b/pkg/next-version
@@ -1 +1 @@
-0.9.2.alpha5
+0.9.2.alpha6
diff --git a/src/leap/bitmask/app.py b/src/leap/bitmask/app.py
index 2c41068c..9412ccd7 100644
--- a/src/leap/bitmask/app.py
+++ b/src/leap/bitmask/app.py
@@ -75,8 +75,9 @@ if platform.system() == "Darwin":
def qt_hack_ubuntu():
- """Export an env var to avoid gui corruption, see #8028"""
+ """Export two env vars to avoid gui corruption, see #8028"""
os.environ['QT_GRAPHICSSYSTEM'] = 'native'
+ os.environ['LIBOVERLAY_SCROLLBAR'] = '0'
def kill_the_children():
--
cgit v1.2.3
From 249864008ae8640042573bd6dfc42b6ce28324e8 Mon Sep 17 00:00:00 2001
From: Kali Kaneko
Date: Thu, 14 Apr 2016 18:49:26 -0400
Subject: [tools] make uploads resumable
---
pkg/pyinst/pyinst-build.mk | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/pkg/pyinst/pyinst-build.mk b/pkg/pyinst/pyinst-build.mk
index 9120e7a1..9595ad50 100644
--- a/pkg/pyinst/pyinst-build.mk
+++ b/pkg/pyinst/pyinst-build.mk
@@ -60,7 +60,7 @@ pyinst-sign:
gpg2 -a --sign --detach-sign dist/Bitmask.$(NEXT_VERSION).tar.gz
pyinst-upload:
- scp dist/Bitmask.$(NEXT_VERSION).* salmon.leap.se:./
+ rsync --rsh='ssh' -avztlpog --progress --partial dist/Bitmask.$(NEXT_VERSION).* salmon.leap.se:./
pyinst-linux: pyinst reset-ver pyinst-hacks pyinst-trim pyinst-cleanup pyinst-distribution-data pyinst-linux-helpers pyinst-tar
--
cgit v1.2.3
From 32b01d729ea8c0e6ecd1bd1def909fc41156d405 Mon Sep 17 00:00:00 2001
From: Kali Kaneko
Date: Thu, 14 Apr 2016 20:25:29 -0400
Subject: [docs] add note about login automation
---
docs/dev/automating_login.rst | 21 +++++++++++++++++++++
1 file changed, 21 insertions(+)
create mode 100644 docs/dev/automating_login.rst
diff --git a/docs/dev/automating_login.rst b/docs/dev/automating_login.rst
new file mode 100644
index 00000000..7017dd8e
--- /dev/null
+++ b/docs/dev/automating_login.rst
@@ -0,0 +1,21 @@
+.. _automating_login:
+
+Automating login
+================
+
+There's an annoying bug with python keyring module, that makes the 'remember
+login' checkbox non functional.
+
+That, and the need to script end-to-end tests with the client inside a docker
+environment, made us put a mechanism to pass credentials via environment
+variables.
+
+To automate login, set BITMASK_CREDENTIALS env var::
+
+ BITMASK_CREDENTIALS=/tmp/secrets.conf bitmask --debug
+
+where the pointed file looks like this::
+
+ [Credentials]
+ username = user@provider
+ password = mypass
--
cgit v1.2.3
From 8361cfdf5f6f56da8e1f7297092d1458a72f9444 Mon Sep 17 00:00:00 2001
From: elijah
Date: Thu, 14 Apr 2016 12:39:26 -0700
Subject: [bug] eip_can_start should return false if provider does not support
eip
otherwise, it tries to open eip config.
- Resolves: #7538
- Releases: 0.9.2
---
src/leap/bitmask/backend/components.py | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/src/leap/bitmask/backend/components.py b/src/leap/bitmask/backend/components.py
index bc34c84c..03a92c88 100644
--- a/src/leap/bitmask/backend/components.py
+++ b/src/leap/bitmask/backend/components.py
@@ -44,7 +44,7 @@ from leap.bitmask.platform_init import IS_LINUX
from leap.bitmask import pix
from leap.bitmask.provider.pinned import PinnedProviders
from leap.bitmask.provider.providerbootstrapper import ProviderBootstrapper
-from leap.bitmask.services import get_supported
+from leap.bitmask.services import get_supported, EIP_SERVICE
from leap.bitmask.services.eip import eipconfig
from leap.bitmask.services.eip import get_openvpn_management
from leap.bitmask.services.eip.eipbootstrapper import EIPBootstrapper
@@ -651,8 +651,10 @@ class EIP(object):
logger.error("No polkit agent running.")
return False
- eip_config = eipconfig.EIPConfig()
provider_config = ProviderConfig.get_provider_config(domain)
+ if EIP_SERVICE not in provider_config.get_services():
+ return False
+ eip_config = eipconfig.EIPConfig()
api_version = provider_config.get_api_version()
eip_config.set_api_version(api_version)
--
cgit v1.2.3
From 15cd7c4a53e9120d032d92382691cc9862f31a8f Mon Sep 17 00:00:00 2001
From: Kali Kaneko
Date: Fri, 15 Apr 2016 15:03:53 -0400
Subject: [doc] update release notes
---
release-notes.rst | 42 ++++++++++++++++++++++++++++--------------
1 file changed, 28 insertions(+), 14 deletions(-)
diff --git a/release-notes.rst b/release-notes.rst
index a9c0ff47..2fc1f9ea 100644
--- a/release-notes.rst
+++ b/release-notes.rst
@@ -1,24 +1,38 @@
0.9.2 April XY - "Panis et Circenses"
-+++++++++++++++++++++++++++++++++++++++++++
++++++++++++++++++++++++++++++++++++++
-We were very pleased to announce Bitmask stable 0.9.2
+We are pleased to announce the Bitmask 0.9.2 release. You can refer to `the
+changelog`_ for the whole changeset.
-This is a minor release and you can see changes on `the changelog`_.
+In addition to the Encrypted Internet Proxy, the Encrypted Email service is now
+available, in Beta state in the Linux bundles. An alpha version for OSX is also
+ready. This service can be tested against any LEAP provider that has made it
+publicly available.
-Using the latest Bitmask, Linux users will be able to use our encrypted email
-service, now in beta state! An alpha version for OSX is also available.
+The "Beta" in the Email service means that things are getting more stable, but
+unforeseen issues are still expected to be found, so please use it accordingly.
+We need you to test it as hard as you can, and report any bugs that you find,
+but don't trust it yet in situations where data loss, delivery problems or any
+other errors can put you at risk or otherwise cause major trouble.
-Currently we have a test provider for mail @ https://mail.bitmask.net This
-provider is already bundled with Bitmask for easy access on the wizard. Please
-help us test this and file bug reports here:
-https://leap.se/code/projects/report-issues
+Currently we maintain a demo provider for the Mail service at
+https://mail.bitmask.net. This provider is already pinned in Bitmask for easy
+access when creating a new account from within the wizard.
-[Pixelated integration news]
+In the standalone bundles beginning with 0.9.2, we are shipping the Pixelated
+Webmail interface. Access via Thunderbird or any other mail client of your
+choice is still supported, but we hope that this modern web interface will make
+the delights of our users.
-The standalone bundles for 0.9.2 include statically compiled binaries for
-OpenVPN 2.3.10 (compiled against PolarSSL 1.3.9) and GnuPG 1.4.20.
+The bundles for 0.9.2 include statically compiled binaries for OpenVPN 2.3.10
+(compiled against PolarSSL 1.3.9) and GnuPG 1.4.20.
-NOTE: beta means that we expect things not to break but we don't promise you
-won't get any headaches or lose some email, so please be careful.
+Please help us test Bitmask and file any bug reports here:
+https://leap.se/code/projects/report-issues, that will be a great contribution
+towards future improvement!
+
+Until the next release, see you on the intertubes, and stay safe.
+
+The Bitmask team.
.. _`the changelog`: https://github.com/leapcode/bitmask_client/blob/0.9.2/CHANGELOG.rst
--
cgit v1.2.3
From e442eb8a3acf8e6bbddaabe7af90cf66d2c755ac Mon Sep 17 00:00:00 2001
From: Kali Kaneko
Date: Fri, 15 Apr 2016 15:04:14 -0400
Subject: [doc] update release checklist
---
docs/release_checklist.wiki | 79 ++++++++++++++++++++++++++++++++++-----------
1 file changed, 60 insertions(+), 19 deletions(-)
diff --git a/docs/release_checklist.wiki b/docs/release_checklist.wiki
index f831d965..7c9dae65 100644
--- a/docs/release_checklist.wiki
+++ b/docs/release_checklist.wiki
@@ -1,25 +1,39 @@
-= Bitmask Release Checklist (*) =
+= Bitmask Release Checklist =
+
+ == CI check ==
* [ ] Check that all tests are passing!
- * [ ] Check that the version in bitmask_client/pkg/linux/bitmask-root is bumped if needed.
+ * [ ] Fix any broken tests.
+
+ == Version bumps and Tagging ==
* [ ] Update pkg/next-release
- * [ ] Tag everything
- * Should be done for the following packages, in order:
+ * [ ] Update release-notes.rst in leap.bitmask if needed.
+ * [ ] Update version in bitmask_client/pkg/linux/bitmask-root if needed.
+
+ * [ ] Tag everything. Should be done for the following packages, in order:
* [ ] 1. leap.common
* [ ] 2. leap.keymanager
* [ ] 3. leap.soledad
* [ ] 4. leap.mail
* [ ] 5. leap.bitmask
* [ ] 6. leap.mx
+
* NOTE: It's assumed that origin is the leap.se repo
+
+ * [ ] export version: export RELEASE=0.9.0
* [ ] git fetch origin
* [ ] git tag -l, and see the latest tagged version (unless it's not a minor version bump, in which case, just bump to it)
- * [ ] Checkout release-X.Y.Z (locally, never pushed)
- * [ ] Update relnotes.txt in leap.bitmask if needed.
+ * [ ] git checkout `release/0.9.x`
+ - NOTE: the release branch is created when the first release candidate
+ is tagged, after that the bugfixes and features that are meant to be
+ shipped with the specific version that we are targetting are merged in that branch
+ * [ ] git checkout -b release/$RELEASE
+ * [ ] (maybe) cherry-pick specific commits
+ * [ ] (maybe) add special fixes for this release
- * [ ] Review pkg/requirements.pip for everything and update if needed (that's why the order).
+ * [ ] Review pkg/requirements.pip for everything, update if needed (that's why the order).
- See whatever has been introduced in changes/VERSION_COMPAT
- Reset changes/VERSION_COMPAT
- * [ ] git commit -av # we should add a commit message here...
+ * [ ] git commit -am "Update requirements file."
* [ ] Fold in changes files into the CHANGELOG
- NOTE: For leap.soledad, the CHANGELOG entries should be divided per package (common, client, server). See older releases for reference.
@@ -27,22 +41,49 @@
* [ ] git rm changes/feature*; git rm changes/bug*
* [ ] git commit -m "Fold in changes."
- * [ ] git checkout master && git pull origin master && git merge --no-ff release-X.Y.Z --no-edit
- * [ ] git tag -s X.Y.Z -m "Tag version X.Y.Z" # (note the -s so that it's a signed tag and -m to specify the message for the tag)
- * [ ] git push origin master; git push origin X.Y.Z
- * [ ] git checkout develop && git merge master && git push origin develop
+ * [ ] git tag --sign $RELEASE -m "Tag leap.bitmask version $RELEASE"
+
+ * If everything went ok, push the changes, and merge back into master&develop:
+ * [ ] git push origin release/0.9.x
+ * [ ] git push origin $RELEASE
+ * [ ] git checkout master && git pull origin master && git merge --no-ff $RELEASE --no-edit
+ * [ ] git checkout develop && git merge $RELEASE && git push origin develop
+
+ == Bundles ==
* [ ] Build and upload bundles
* [ ] Use 'make pyinst-linux' to build bundles.
- * [ ] Sign them with gpg -a --sign --detach-sign
+ * [ ] Sign: make pyinst-sign
* [ ] Upload bundle and signature to downloads.leap.se/client//Bitmask--.(tar.bz2,dmg,zip)
+ * [ ] make pyinst-upload
* [ ] Update symbolic link for latest upload and signature:
* [ ] ~/public/client/Bitmask--latest
* [ ] ~/public/client/Bitmask--latest.asc
- * [ ] Announce
- * [ ] Mail leap@lists.riseup.net
-Notes
------
-(*) this checklist kindly borrowed from tahoe-lafs documentation =)
+ === TUF: Relese candidate bundles: RC# (skipped for now) ===
+ * [ ] Upload the TUF unstable repo
+ * [ ] Upload bundle to staging for release-candidate
+ * [ ] Sign the bundles, move it to client downloads (micah)
+ * [ ] Update symlinks for -latest
+ * [ ] Fix all show stoppers
-For a good reference look at http://nvie.com/posts/a-successful-git-branching-model/
+ === TUF: Stable bundles (skipped for now) ===
+ * [ ] Upload the TUF Stable Repo to staging
+ * [ ] Upload bundle to staging for stable
+ * [ ] move and sign the TUF repo (kwadro)
+ * [ ] Sign the bundles, move it to client downloads (micah)
+ * [ ] Update symlinks for -latest
+
+ == Debian packages ==
+ * TBD...
+
+ == Pypi upload ==
+ * [ ] python setup.py sdist upload --sign -i kali@leap.se -r pypi
+
+ == Announcing ==
+ * [ ] Announce (use release-notes.rst)
+ * [ ] Mail leap@lists.riseup.net
+ * [ ] Twitter
+ * [ ] Gnusocial
+ * [ ] Post in leap.se
+ * [ ] reddit
+ * [ ] hackernews
--
cgit v1.2.3
From 92f4b40ab48ec537aade244af3e3e4f2c17b1475 Mon Sep 17 00:00:00 2001
From: Kali Kaneko
Date: Fri, 15 Apr 2016 16:10:00 -0400
Subject: [refactor] adapt to the new Account signature
---
src/leap/bitmask/pix.py | 2 +-
src/leap/bitmask/services/mail/imap.py | 2 +-
src/leap/bitmask/services/mail/plumber.py | 3 ++-
3 files changed, 4 insertions(+), 3 deletions(-)
diff --git a/src/leap/bitmask/pix.py b/src/leap/bitmask/pix.py
index 8d7d0811..b510106d 100644
--- a/src/leap/bitmask/pix.py
+++ b/src/leap/bitmask/pix.py
@@ -140,7 +140,7 @@ class LeapSessionAdapter(object):
self.fresh_account = False
self.incoming_mail_fetcher = None
- self.account = Account(soledad)
+ self.account = Account(soledad, userid)
username, provider = userid.split('@')
smtp_client_cert = os.path.join(
diff --git a/src/leap/bitmask/services/mail/imap.py b/src/leap/bitmask/services/mail/imap.py
index 54935f8c..2f000b2a 100644
--- a/src/leap/bitmask/services/mail/imap.py
+++ b/src/leap/bitmask/services/mail/imap.py
@@ -91,7 +91,7 @@ def start_incoming_mail_service(keymanager, soledad, userid):
check_period=get_mail_check_period())
return incoming_mail
- acc = Account(soledad)
+ acc = Account(soledad, userid)
d = acc.callWhenReady(lambda _: acc.get_collection_by_mailbox(INBOX_NAME))
d.addCallback(setUpIncomingMail)
d.addErrback(log.err)
diff --git a/src/leap/bitmask/services/mail/plumber.py b/src/leap/bitmask/services/mail/plumber.py
index 43203f0c..cd1f06bb 100644
--- a/src/leap/bitmask/services/mail/plumber.py
+++ b/src/leap/bitmask/services/mail/plumber.py
@@ -60,6 +60,7 @@ def initialize_soledad(uuid, email, passwd,
cert_file = ""
class Mock(object):
+
def __init__(self, return_value=None):
self._return = return_value
@@ -140,7 +141,7 @@ class MBOXPlumber(object):
self.sol = initialize_soledad(
self.uuid, self.userid, self.passwd,
secrets, localdb, "/tmp", "/tmp")
- self.acct = IMAPAccount(self.userid, self.sol)
+ self.acct = IMAPAccount(self.sol, self.userid)
return True
#
--
cgit v1.2.3
From 0a5d24d64b5f637038a15b01bbe1b3d4bf4108f2 Mon Sep 17 00:00:00 2001
From: Paixu Aabuizia
Date: Sun, 10 Jan 2016 15:40:35 +0100
Subject: [pkg] reproducible windows installer for bitmask_client
provide a environment that allows automated builds of windows installers
- prepare dockerized environment with wine, python, openssl, zlib and mingw
to build windows binaries from python sourcecode
- prepare dockerized environment with nullsoft installer
to build installers from binaries
- configure pyinstaller to build binaries
- configure nsis to build distributable executables for bitmask
- configure make all in pkg/windows that results in installers
- add documentation
- ico conversion from data/images
- avoid polluting / in docker image
- install dirspec and copy to wine env
- remove obsolete comments
- fix python path
- figure out that pip install leap.a and pyinstalling a leap.b does not work - so the build script fixes that
- rename dependencies to pyinstaller and move nsis code to installer
- build openvpn, export the binaries for further processing
- correct openvpn dependencies, fetch tap installer compatible with openvpn just built
- install tap-driver with nsis
- pyinstaller-build: fix mixed mkdir / show errors if there are some
- installer-build: prepare rw-copy, do not expose nsh files
- add openvpn_leap.exe to install directory so it gets picked up by nsis
- use setup.py to install bitmask to site-packages to have a version
- separate build directories for granular make
- copy all openvpn dlls to installer
- die to signal failure to parent makefile
- cache installDependencies for quick turn-arround times
- share openssl version between openvpn and pysqlcipher/other pip builds
- collect files during prepare for installer
- default to eip:false, mail:true
- configuration in pyinstaller-build.sh
- win64 tap drivers need special care getting removed from 32bit nsis
- correct registry key that identifies if we installed TAP
- extract version from git-tree, expose to wine python
- create nsh with version for build installer
- allow clean/dirty version with patches
- cleanup / indent / remove comments
- die when pysqlchipher patch failed
- add psutil in mingw compatible version
---
pkg/pyinst/bitmask.spec | 30 ++-
pkg/pyinst/qt.conf | 2 +
pkg/windows/Makefile | 25 ++
pkg/windows/README.rst | 144 +++++++++++
pkg/windows/TODO | 15 ++
pkg/windows/bitmask.nis | 2 +
pkg/windows/bitmask.nsh | 115 +++++++++
pkg/windows/bitmask_client_product.nsh | 8 +
pkg/windows/bitmask_client_registry_install.nsh | 17 ++
pkg/windows/docker-compose.yml | 42 +++
pkg/windows/installer-build.sh | 119 +++++++++
pkg/windows/installer/Dockerfile | 17 ++
pkg/windows/openvpn-build.sh | 62 +++++
pkg/windows/openvpn/Dockerfile | 17 ++
pkg/windows/pyinstaller-build.sh | 287 +++++++++++++++++++++
pkg/windows/pyinstaller/Dockerfile | 105 ++++++++
pkg/windows/pyinstaller/pysqlcipher_setup.py.patch | 14 +
pkg/windows/pyinstaller/zlib-mingw-shared.patch | 10 +
18 files changed, 1024 insertions(+), 7 deletions(-)
create mode 100644 pkg/pyinst/qt.conf
create mode 100644 pkg/windows/Makefile
create mode 100644 pkg/windows/README.rst
create mode 100644 pkg/windows/TODO
create mode 100644 pkg/windows/bitmask.nis
create mode 100644 pkg/windows/bitmask.nsh
create mode 100644 pkg/windows/bitmask_client_product.nsh
create mode 100644 pkg/windows/bitmask_client_registry_install.nsh
create mode 100644 pkg/windows/docker-compose.yml
create mode 100755 pkg/windows/installer-build.sh
create mode 100644 pkg/windows/installer/Dockerfile
create mode 100755 pkg/windows/openvpn-build.sh
create mode 100644 pkg/windows/openvpn/Dockerfile
create mode 100755 pkg/windows/pyinstaller-build.sh
create mode 100644 pkg/windows/pyinstaller/Dockerfile
create mode 100644 pkg/windows/pyinstaller/pysqlcipher_setup.py.patch
create mode 100644 pkg/windows/pyinstaller/zlib-mingw-shared.patch
diff --git a/pkg/pyinst/bitmask.spec b/pkg/pyinst/bitmask.spec
index a76ccb17..cd207816 100644
--- a/pkg/pyinst/bitmask.spec
+++ b/pkg/pyinst/bitmask.spec
@@ -3,17 +3,32 @@ import sys
block_cipher = None
-
-a = Analysis([os.path.join('bitmask.py')],
+a = Analysis(['bitmask.py'],
hiddenimports=[
- 'zope.interface', 'zope.proxy',
- 'PySide.QtCore', 'PySide.QtGui', 'PySide.QtWebKit'],
+ 'zope.interface', 'zope.proxy',
+ 'PySide.QtCore', 'PySide.QtGui',
+ 'pysqlcipher', 'service_identity',
+ 'leap.common', 'leap.bitmask'
+ ],
+ binaries=None,
+ datas=None,
hookspath=None,
runtime_hooks=None,
excludes=None,
+ win_no_prefer_redirects=None,
+ win_private_assemblies=None,
cipher=block_cipher)
-pyz = PYZ(a.pure,
+pyz = PYZ(a.pure, a.zipped_data,
cipher=block_cipher)
+
+# Binary files you need to include in the form of:
+# (,
@@ -60,6 +60,24 @@
16777215
+
+ background: palette(base); border: 1px solid palette(dark); border-radius: 2px;
+
+
+ QFrame::StyledPanel
+
+
+ QFrame::Plain
+
+
+ 1
+
+
+ 0
+
+
+ Qt::ScrollBarAlwaysOff
+ 32
diff --git a/src/leap/bitmask/gui/ui/preferences_email_page.ui b/src/leap/bitmask/gui/ui/preferences_email_page.ui
index 7cc5bb3c..5f83426b 100644
--- a/src/leap/bitmask/gui/ui/preferences_email_page.ui
+++ b/src/leap/bitmask/gui/ui/preferences_email_page.ui
@@ -6,13 +6,572 @@
00
- 400
- 300
+ 526
+ 605Form
+
+
+ 0
+
+
+ 0
+
+
+
+
+ 2
+
+
+
+
+
+
+
+
+
+ Tab 1
+
+
+
+
+
+ Thunderbird Configuration
+
+
+
+
+
+ thunderbird information
+
+
+ true
+
+
+
+
+
+
+
+
+
+
+ 0
+ 0
+
+
+
+ Mail Client Configuration
+
+
+
+
+
+ mail client information
+
+
+ true
+
+
+
+
+
+
+
+
+
+
+
+ 0
+ 0
+
+
+
+ Host
+
+
+ Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
+
+
+
+
+
+
+
+ 0
+ 0
+
+
+
+ Port
+
+
+ Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
+
+
+
+
+
+
+
+ 0
+ 0
+
+
+
+
+ 100
+ 16777215
+
+
+
+
+
+
+ true
+
+
+
+
+
+
+
+ 0
+ 0
+
+
+
+ TLS: off
+
+
+
+
+
+
+
+ 0
+ 0
+
+
+
+
+ 50
+ 16777215
+
+
+
+ true
+
+
+
+
+
+
+ Qt::Horizontal
+
+
+
+ 40
+ 20
+
+
+
+
+
+
+
+
+
+ IMAP
+
+
+
+
+
+
+ Username
+
+
+
+
+
+
+ SMTP
+
+
+
+
+
+
+
+
+
+ 0
+ 0
+
+
+
+ Host
+
+
+ Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
+
+
+
+
+
+
+
+ 0
+ 0
+
+
+
+
+ 100
+ 16777215
+
+
+
+
+
+
+ true
+
+
+
+
+
+
+
+ 0
+ 0
+
+
+
+ Port
+
+
+ Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
+
+
+
+
+
+
+ Qt::Horizontal
+
+
+
+ 40
+ 20
+
+
+
+
+
+
+
+
+ 0
+ 0
+
+
+
+ TLS: off
+
+
+
+
+
+
+
+ 0
+ 0
+
+
+
+
+ 50
+ 16777215
+
+
+
+ true
+
+
+
+
+
+
+
+
+ true
+
+
+
+
+
+
+ Password
+
+
+
+
+
+
+ true
+
+
+
+
+
+
+
+
+
+
+
+ Qt::Vertical
+
+
+
+ 20
+ 40
+
+
+
+
+
+
+
+
+ Tab 2
+
+
+
+
+
+
+
+
+ Public Key
+
+
+
+
+
+
+
+ 0
+ 0
+
+
+
+
+ Courier
+
+
+
+ QPlainTextEdit::NoWrap
+
+
+ true
+
+
+
+
+
+
+
+ 0
+ 42
+
+
+
+
+ 16777215
+ 48
+
+
+
+
+ Courier
+ 50
+ false
+
+
+
+ false
+
+
+
+
+
+ QPlainTextEdit::NoWrap
+
+
+ true
+
+
+
+
+
+
+
+
+
+ Expiration
+
+
+
+
+
+
+ Fingerprint
+
+
+
+
+
+
+ true
+
+
+
+
+
+ Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter
+
+
+ true
+
+
+
+
+
+
+ Address
+
+
+
+
+
+
+ true
+
+
+
+
+
+
+
+
+ Export Private Key
+
+
+
+
+
+
+ Import Private Key
+
+
+
+
+
+
+ Qt::Horizontal
+
+
+
+ 40
+ 20
+
+
+
+
+
+
+
+ uid_edit
+ fp_label
+ uid_label
+ expiration_edit
+ expiration_label
+ fingerprint_edit
+ public_key_edit
+ pub_label
+
+
+
+
+
+
+ Qt::Vertical
+
+
+
+ 20
+ 40
+
+
+
+
+
+
+
+
+ Page
+
+
+
+
+
+ QAbstractItemView::NoEditTriggers
+
+
+ true
+
+
+ QAbstractItemView::SingleSelection
+
+
+ QAbstractItemView::SelectRows
+
+
+ Qt::ElideRight
+
+
+ true
+
+
+
+ Email
+
+
+
+
+ Key ID
+
+
+
+
+
+
+
+
+
+
+
+ this message should be hidden
+
+
+
+
--
cgit v1.2.3
From 5b90ad3552025436edb40665203ab98eceaa065b Mon Sep 17 00:00:00 2001
From: Kali Kaneko
Date: Tue, 19 Apr 2016 12:07:09 -0400
Subject: pep8/flake8
---
src/leap/bitmask/core/service.py | 4 +--
src/leap/bitmask/gui/account.py | 1 +
src/leap/bitmask/gui/app.py | 4 +--
src/leap/bitmask/gui/mainwindow.py | 8 +++---
src/leap/bitmask/gui/preferences_account_page.py | 1 -
src/leap/bitmask/gui/preferences_email_page.py | 36 ++++++++++++------------
src/leap/bitmask/gui/preferences_page.py | 6 ++--
src/leap/bitmask/gui/preferences_vpn_page.py | 2 +-
src/leap/bitmask/gui/preferenceswindow.py | 7 +++--
src/leap/bitmask/gui/statemachines.py | 5 +++-
src/leap/bitmask/services/eip/vpnprocess.py | 1 -
11 files changed, 39 insertions(+), 36 deletions(-)
diff --git a/src/leap/bitmask/core/service.py b/src/leap/bitmask/core/service.py
index 87349ef6..13c8864a 100644
--- a/src/leap/bitmask/core/service.py
+++ b/src/leap/bitmask/core/service.py
@@ -29,7 +29,7 @@ from leap.bitmask.core import _zmq
from leap.bitmask.core import websocket
from leap.bonafide.service import BonafideService
from leap.common.events import server as event_server
-#from leap.vpn import EIPService
+# from leap.vpn import EIPService
class BitmaskBackend(configurable.ConfigurableService):
@@ -96,7 +96,7 @@ class BitmaskBackend(configurable.ConfigurableService):
def init_eip(self):
# FIXME -- land EIP into leap.vpn
pass
- #self._maybe_start_service('eip', EIPService)
+ # self._maybe_start_service('eip', EIPService)
def init_zmq(self):
zs = _zmq.ZMQServerService(self)
diff --git a/src/leap/bitmask/gui/account.py b/src/leap/bitmask/gui/account.py
index 5e43c8fe..b8b9509a 100644
--- a/src/leap/bitmask/gui/account.py
+++ b/src/leap/bitmask/gui/account.py
@@ -22,6 +22,7 @@ from leap.bitmask.config.leapsettings import LeapSettings
from leap.bitmask.services import EIP_SERVICE, MX_SERVICE
from leap.bitmask._components import HAS_EIP, HAS_MAIL
+
class Account():
def __init__(self, username, domain):
diff --git a/src/leap/bitmask/gui/app.py b/src/leap/bitmask/gui/app.py
index e3a4d7fe..1011454e 100644
--- a/src/leap/bitmask/gui/app.py
+++ b/src/leap/bitmask/gui/app.py
@@ -60,8 +60,8 @@ class App(QtGui.QWidget):
def current_account(self):
"""
- Alas, the only definitive account information is buried in the memory of
- QT widgets.
+ Alas, the only definitive account information is buried in the memory
+ of QT widgets.
:returns: an object representing the current user account.
:rtype: Account
diff --git a/src/leap/bitmask/gui/mainwindow.py b/src/leap/bitmask/gui/mainwindow.py
index ca14e631..daf49eb6 100644
--- a/src/leap/bitmask/gui/mainwindow.py
+++ b/src/leap/bitmask/gui/mainwindow.py
@@ -154,11 +154,11 @@ class MainWindow(QtGui.QMainWindow, SignalTracker):
self._providers = Providers(self.ui.cmbProviders)
##
- ## tmphack: important state information about the application is stored
- ## in widgets. Rather than rewrite the UI, for now we simulate this
- ## info being stored in an application object:
+ # tmphack: important state information about the application is stored
+ # in widgets. Rather than rewrite the UI, for now we simulate this
+ # info being stored in an application object:
##
- self.app.login_state = self._login_widget._state
+ self.app.login_state = self._login_widget._state
self.app.providers_widget = self._providers
# Qt Signal Connections #####################################
diff --git a/src/leap/bitmask/gui/preferences_account_page.py b/src/leap/bitmask/gui/preferences_account_page.py
index c175c42b..141523c8 100644
--- a/src/leap/bitmask/gui/preferences_account_page.py
+++ b/src/leap/bitmask/gui/preferences_account_page.py
@@ -69,7 +69,6 @@ class PreferencesAccountPage(PreferencesPage):
self.app.signaler.prov_get_supported_services.connect(
self._load_services)
-
def teardown_connections(self):
"""
disconnect signals
diff --git a/src/leap/bitmask/gui/preferences_email_page.py b/src/leap/bitmask/gui/preferences_email_page.py
index 50f244fb..8211aeb8 100644
--- a/src/leap/bitmask/gui/preferences_email_page.py
+++ b/src/leap/bitmask/gui/preferences_email_page.py
@@ -18,8 +18,6 @@ Widget for "email" preferences
"""
from PySide import QtCore, QtGui
-from datetime import datetime
-
from leap.bitmask.logs.utils import get_logger
from leap.bitmask.gui.ui_preferences_email_page import Ui_PreferencesEmailPage
from leap.bitmask.gui.preferences_page import PreferencesPage
@@ -27,6 +25,7 @@ from leap.mail.imap.service.imap import IMAP_PORT
logger = get_logger()
+
class PreferencesEmailPage(PreferencesPage):
def __init__(self, parent, account, app):
@@ -46,11 +45,11 @@ class PreferencesEmailPage(PreferencesPage):
# the only way to set the tab titles is to re-add them:
self.ui.email_tabs.addTab(self.ui.config_tab,
- self.tr("Mail Client"))
+ self.tr("Mail Client"))
self.ui.email_tabs.addTab(self.ui.my_key_tab,
- self.tr("My Key"))
+ self.tr("My Key"))
self.ui.email_tabs.addTab(self.ui.other_keys_tab,
- self.tr("Other Keys"))
+ self.tr("Other Keys"))
# set mail client configuration help text
lang = QtCore.QLocale.system().name().replace('_', '-')
@@ -61,7 +60,7 @@ class PreferencesEmailPage(PreferencesPage):
"For Thunderbird, you can use the Bitmask extension. "
"Search for \"Bitmask\" in the add-on manager or "
"download it from addons.mozilla.org.".format(
- thunderbird_extension_url)))
+ thunderbird_extension_url)))
self.ui.mail_client_label.setText(self.tr(
"Alternatively, you can manually configure your mail client to "
"use Bitmask Email with these options:"))
@@ -71,7 +70,6 @@ class PreferencesEmailPage(PreferencesPage):
self.setup_connections()
-
def setup_connections(self):
"""
connect signals
@@ -106,7 +104,7 @@ class PreferencesEmailPage(PreferencesPage):
self.ui.message_label.setText(
self.tr('You must be logged in to edit email settings.'))
else:
- self.ui.import_button.setVisible(False) # hide this until working
+ self.ui.import_button.setVisible(False) # hide this until working
self.ui.message_label.setVisible(False)
self.ui.email_tabs.setVisible(True)
smtp_port = 2013
@@ -128,7 +126,7 @@ class PreferencesEmailPage(PreferencesPage):
Set the current user's key details into the gui.
"""
self.ui.fingerprint_edit.setPlainText(
- self._format_fingerprint(details["fingerprint"]))
+ self._format_fingerprint(details["fingerprint"]))
self.ui.expiration_edit.setText(details["expiry_date"])
self.ui.uid_edit.setText(" ".join(details["uids"]))
self.ui.public_key_edit.setPlainText(details["key_data"])
@@ -139,8 +137,8 @@ class PreferencesEmailPage(PreferencesPage):
produces, wrapped to two lines.
"""
fp = fingerprint.upper()
- fp_list = [fp[i:i+4] for i in range(0, len(fp), 4)]
- fp_wrapped = " ".join(fp_list[0:5]) + "\n" + " ".join(fp_list[5:10])
+ fp_list = [fp[i:i + 4] for i in range(0, len(fp), 4)]
+ fp_wrapped = " ".join(fp_list[0:5]) + "\n" + " ".join(fp_list[5:10])
return fp_wrapped
def _export_keys(self):
@@ -156,8 +154,8 @@ class PreferencesEmailPage(PreferencesPage):
if not file_name.endswith('.pem'):
file_name += '.pem'
self.app.backend.keymanager_export_keys(
- username=self.account.address,
- filename=file_name)
+ username=self.account.address,
+ filename=file_name)
else:
logger.debug('Export canceled by the user.')
@@ -186,9 +184,9 @@ class PreferencesEmailPage(PreferencesPage):
"Export canceled."))
def _import_keys(self):
- """
- not yet supported
- """
+ """
+ not yet supported
+ """
def _keymanager_keys_list(self, keys):
"""
@@ -203,5 +201,7 @@ class PreferencesEmailPage(PreferencesPage):
for key in keys:
row = self.ui.keys_table.rowCount()
self.ui.keys_table.insertRow(row)
- self.ui.keys_table.setItem(row, 0, QtGui.QTableWidgetItem(key.address))
- self.ui.keys_table.setItem(row, 1, QtGui.QTableWidgetItem(key.fingerprint))
+ self.ui.keys_table.setItem(
+ row, 0, QtGui.QTableWidgetItem(key.address))
+ self.ui.keys_table.setItem(
+ row, 1, QtGui.QTableWidgetItem(key.fingerprint))
diff --git a/src/leap/bitmask/gui/preferences_page.py b/src/leap/bitmask/gui/preferences_page.py
index c75b4991..a5d811f9 100644
--- a/src/leap/bitmask/gui/preferences_page.py
+++ b/src/leap/bitmask/gui/preferences_page.py
@@ -14,10 +14,11 @@
# You should have received a copy of the GNU General Public License
# along with this program. If not, see .
"""
-base class for preference pages
+Base class for preference pages
"""
-from PySide import QtCore, QtGui
+from PySide import QtGui
+
class PreferencesPage(QtGui.QWidget):
@@ -47,4 +48,3 @@ class PreferencesPage(QtGui.QWidget):
disconnect signals
must be overridden by subclass
"""
-
diff --git a/src/leap/bitmask/gui/preferences_vpn_page.py b/src/leap/bitmask/gui/preferences_vpn_page.py
index fc15340f..87b86c4e 100644
--- a/src/leap/bitmask/gui/preferences_vpn_page.py
+++ b/src/leap/bitmask/gui/preferences_vpn_page.py
@@ -20,10 +20,10 @@ Widget for "vpn" preferences
from PySide import QtCore, QtGui
from leap.bitmask.gui.ui_preferences_vpn_page import Ui_PreferencesVpnPage
-from leap.bitmask.config.leapsettings import LeapSettings
from leap.bitmask.gui.flashable import Flashable
from leap.bitmask.gui.preferences_page import PreferencesPage
+
class PreferencesVpnPage(PreferencesPage, Flashable):
"""
diff --git a/src/leap/bitmask/gui/preferenceswindow.py b/src/leap/bitmask/gui/preferenceswindow.py
index 1facba69..82dc8d77 100644
--- a/src/leap/bitmask/gui/preferenceswindow.py
+++ b/src/leap/bitmask/gui/preferenceswindow.py
@@ -29,6 +29,7 @@ from leap.bitmask.gui.preferences_email_page import PreferencesEmailPage
logger = get_logger()
+
class PreferencesWindow(QtGui.QDialog):
"""
@@ -122,7 +123,7 @@ class PreferencesWindow(QtGui.QDialog):
"""
Adds the pages for the different configuration categories.
"""
- self._remove_pages() # in case different account was loaded.
+ self._remove_pages() # in case different account was loaded.
# load placeholder widgets if the page should not be loaded.
# the order of the pages is important, and must match the order
@@ -197,8 +198,8 @@ class PreferencesWindow(QtGui.QDialog):
Close this dialog and destroy it.
"""
PreferencesWindow._current_window = None
- self._teardown_connections();
- self._remove_pages();
+ self._teardown_connections()
+ self._remove_pages()
self.deleteLater()
def _change_page(self, current, previous):
diff --git a/src/leap/bitmask/gui/statemachines.py b/src/leap/bitmask/gui/statemachines.py
index ab48b756..92c5431d 100644
--- a/src/leap/bitmask/gui/statemachines.py
+++ b/src/leap/bitmask/gui/statemachines.py
@@ -40,6 +40,7 @@ class SignallingState(QState):
"""
A state that emits a custom signal on entry.
"""
+
def __init__(self, signal, parent=None, name=None):
"""
Initializer.
@@ -134,6 +135,7 @@ class States(object):
class CompositeEvent(QtCore.QEvent):
+
def __init__(self):
super(CompositeEvent, self).__init__(
QtCore.QEvent.Type(self.ID))
@@ -174,6 +176,7 @@ class Events(QtCore.QObject):
A Wrapper object for containing the events that will be
posted to a composite state machine.
"""
+
def __init__(self, parent=None):
"""
Initializes the QObject with the given parent.
@@ -289,6 +292,7 @@ class ConnectionMachineBuilder(object):
"""
Builder class for state machines made from LEAPConnections.
"""
+
def __init__(self, connection):
"""
:param connection: an instance of a concrete LEAPConnection
@@ -352,7 +356,6 @@ class ConnectionMachineBuilder(object):
:rtype: QStateMachine
"""
# TODO split this method in smaller utility functions.
- parent = kwargs.get('parent', None)
# 1. create machine
machine = CompositeMachine()
diff --git a/src/leap/bitmask/services/eip/vpnprocess.py b/src/leap/bitmask/services/eip/vpnprocess.py
index de8d92f3..580bd572 100644
--- a/src/leap/bitmask/services/eip/vpnprocess.py
+++ b/src/leap/bitmask/services/eip/vpnprocess.py
@@ -23,7 +23,6 @@ import shutil
import socket
import subprocess
import sys
-import time
from itertools import chain, repeat
--
cgit v1.2.3
From ca2e16bb9fbef938bc17b232e801d484d9602ec4 Mon Sep 17 00:00:00 2001
From: Kali Kaneko
Date: Tue, 19 Apr 2016 12:09:43 -0400
Subject: [docs] add email prefs to changelog
---
changes/feature-7552_mail-help-message-on-ui | 1 -
changes/feature-email-preferences-panel | 1 -
changes/next-changelog.rst | 1 +
3 files changed, 1 insertion(+), 2 deletions(-)
delete mode 100644 changes/feature-7552_mail-help-message-on-ui
delete mode 100644 changes/feature-email-preferences-panel
diff --git a/changes/feature-7552_mail-help-message-on-ui b/changes/feature-7552_mail-help-message-on-ui
deleted file mode 100644
index 44ab8fa7..00000000
--- a/changes/feature-7552_mail-help-message-on-ui
+++ /dev/null
@@ -1 +0,0 @@
-- Add UI message to help new mail users to get started. Closes feature #7552.
diff --git a/changes/feature-email-preferences-panel b/changes/feature-email-preferences-panel
deleted file mode 100644
index e9bbfb6a..00000000
--- a/changes/feature-email-preferences-panel
+++ /dev/null
@@ -1 +0,0 @@
-- Add email panel to preferences window.
\ No newline at end of file
diff --git a/changes/next-changelog.rst b/changes/next-changelog.rst
index 4f09b291..ca74746f 100644
--- a/changes/next-changelog.rst
+++ b/changes/next-changelog.rst
@@ -16,6 +16,7 @@ Features
- `#6041 `_: Write service tokens to a file to allow email clients to read them from there.
- Use cred-based authentication on SMTP.
- Experimental support for the Pixelated WebMail.
+- Add email panel to preferences window.
- Ability to launch detached bitmask.core daemon, and a simplistic bitmask_cli. Not used by the main client yet.
- `#1234 `_: Description of the new feature corresponding with issue #1234.
--
cgit v1.2.3
From 80078e7e85cb40485e74bf7cf9a93d9db5592400 Mon Sep 17 00:00:00 2001
From: Kali Kaneko
Date: Tue, 19 Apr 2016 12:17:59 -0400
Subject: [pkg] bump version_compat with keymanager version
---
changes/VERSION_COMPAT | 2 ++
1 file changed, 2 insertions(+)
diff --git a/changes/VERSION_COMPAT b/changes/VERSION_COMPAT
index 660f9640..cd698ae7 100644
--- a/changes/VERSION_COMPAT
+++ b/changes/VERSION_COMPAT
@@ -11,3 +11,5 @@
#
# BEGIN DEPENDENCY LIST -------------------------
# leap.foo.bar>=x.y.z
+
+leap.keymanager >= 0.5.1
--
cgit v1.2.3
From 9a0568c18ed38558a481d5f6e4be12c68f9870a6 Mon Sep 17 00:00:00 2001
From: Kali Kaneko
Date: Tue, 19 Apr 2016 13:14:54 -0400
Subject: [feature] enable webmail from the mail preferences window
this box is only visible when the HAS_PIXELATED flag is True, that
means we have pixelated-user-agent and pixelated-www in the environment.
- Releases: 0.9.2
---
src/leap/bitmask/config/leapsettings.py | 2 +-
src/leap/bitmask/gui/preferences_email_page.py | 19 ++++++++++++++
src/leap/bitmask/gui/ui/preferences_email_page.ui | 30 +++++++++++++++++++++--
3 files changed, 48 insertions(+), 3 deletions(-)
diff --git a/src/leap/bitmask/config/leapsettings.py b/src/leap/bitmask/config/leapsettings.py
index 01900484..075be8a7 100644
--- a/src/leap/bitmask/config/leapsettings.py
+++ b/src/leap/bitmask/config/leapsettings.py
@@ -360,4 +360,4 @@ class LeapSettings(object):
def set_pixelmail_enabled(self, enabled):
leap_assert_type(enabled, bool)
- self._settings.setvalue(self.PIXELMAIL_KEY, enabled)
+ self._settings.setValue(self.PIXELMAIL_KEY, enabled)
diff --git a/src/leap/bitmask/gui/preferences_email_page.py b/src/leap/bitmask/gui/preferences_email_page.py
index 8211aeb8..b8633f07 100644
--- a/src/leap/bitmask/gui/preferences_email_page.py
+++ b/src/leap/bitmask/gui/preferences_email_page.py
@@ -18,11 +18,14 @@ Widget for "email" preferences
"""
from PySide import QtCore, QtGui
+from leap.bitmask.config.leapsettings import LeapSettings
from leap.bitmask.logs.utils import get_logger
from leap.bitmask.gui.ui_preferences_email_page import Ui_PreferencesEmailPage
from leap.bitmask.gui.preferences_page import PreferencesPage
+from leap.bitmask.pix import HAS_PIXELATED
from leap.mail.imap.service.imap import IMAP_PORT
+
logger = get_logger()
@@ -40,6 +43,7 @@ class PreferencesEmailPage(PreferencesPage):
:type app: App
"""
PreferencesPage.__init__(self, parent, account, app)
+ self.settings = LeapSettings()
self.ui = Ui_PreferencesEmailPage()
self.ui.setupUi(self)
@@ -65,6 +69,16 @@ class PreferencesEmailPage(PreferencesPage):
"Alternatively, you can manually configure your mail client to "
"use Bitmask Email with these options:"))
+ self.ui.webmail_label.setText(self.tr(
+ "This distribution of Bitmask ships an experimental integration "
+ "of the Pixelated "
+ "Webmail. It is not stable yet, but you can enable it to help "
+ "beta-testing it. (Needs restart!)"))
+ webmail_enabled = self.settings.get_pixelmail_enabled()
+ self.ui.webmail_checkbox.setChecked(webmail_enabled)
+ if not HAS_PIXELATED:
+ self.ui.webmail_box.setVisible(False)
+
self.ui.keys_table.horizontalHeader().setResizeMode(
0, QtGui.QHeaderView.Stretch)
@@ -81,6 +95,7 @@ class PreferencesEmailPage(PreferencesPage):
self._keymanager_export_error)
self.ui.import_button.clicked.connect(self._import_keys)
self.ui.export_button.clicked.connect(self._export_keys)
+ self.ui.webmail_checkbox.stateChanged.connect(self._toggle_webmail)
def teardown_connections(self):
"""
@@ -205,3 +220,7 @@ class PreferencesEmailPage(PreferencesPage):
row, 0, QtGui.QTableWidgetItem(key.address))
self.ui.keys_table.setItem(
row, 1, QtGui.QTableWidgetItem(key.fingerprint))
+
+ def _toggle_webmail(self, state):
+ value = True if state == QtCore.Qt.Checked else False
+ self.settings.set_pixelmail_enabled(value)
diff --git a/src/leap/bitmask/gui/ui/preferences_email_page.ui b/src/leap/bitmask/gui/ui/preferences_email_page.ui
index 5f83426b..22d690d9 100644
--- a/src/leap/bitmask/gui/ui/preferences_email_page.ui
+++ b/src/leap/bitmask/gui/ui/preferences_email_page.ui
@@ -23,7 +23,7 @@
- 2
+ 0
@@ -35,7 +35,7 @@
Tab 1
-
+
@@ -332,6 +332,32 @@
+
+
+
+ Webmail Configuration
+
+
+
+
+
+ Enable Bitmask Webmail (beta)
+
+
+
+
+
+
+ webmail info
+
+
+ true
+
+
+
+
+
+
--
cgit v1.2.3
From a68bbe5e69a3481ede78f518b1637761e8f8cd01 Mon Sep 17 00:00:00 2001
From: Ruben Pollan
Date: Wed, 20 Apr 2016 12:44:15 -0300
Subject: [bug] let the failure propagate
The failure was processed in start_incoming_mail_service what will make
it return a None when an IncomingMail object was expected. If we
propagate the failure it can be treated properly by the IMAPController.
- Related: #8051
---
src/leap/bitmask/services/mail/imap.py | 1 -
1 file changed, 1 deletion(-)
diff --git a/src/leap/bitmask/services/mail/imap.py b/src/leap/bitmask/services/mail/imap.py
index 2f000b2a..7875a4af 100644
--- a/src/leap/bitmask/services/mail/imap.py
+++ b/src/leap/bitmask/services/mail/imap.py
@@ -94,5 +94,4 @@ def start_incoming_mail_service(keymanager, soledad, userid):
acc = Account(soledad, userid)
d = acc.callWhenReady(lambda _: acc.get_collection_by_mailbox(INBOX_NAME))
d.addCallback(setUpIncomingMail)
- d.addErrback(log.err)
return d
--
cgit v1.2.3
From b6bf547e3a8b96b5fcdba739ed4be74bf040a7ed Mon Sep 17 00:00:00 2001
From: Kali Kaneko
Date: Mon, 25 Apr 2016 17:25:36 -0400
Subject: [refactor] move the pixelated panel upwards
---
src/leap/bitmask/gui/preferences_email_page.py | 7 +--
src/leap/bitmask/gui/qt_browser.py | 2 +-
src/leap/bitmask/gui/ui/preferences_email_page.ui | 54 +++++++++++------------
3 files changed, 32 insertions(+), 31 deletions(-)
diff --git a/src/leap/bitmask/gui/preferences_email_page.py b/src/leap/bitmask/gui/preferences_email_page.py
index b8633f07..f6d6f036 100644
--- a/src/leap/bitmask/gui/preferences_email_page.py
+++ b/src/leap/bitmask/gui/preferences_email_page.py
@@ -71,9 +71,10 @@ class PreferencesEmailPage(PreferencesPage):
self.ui.webmail_label.setText(self.tr(
"This distribution of Bitmask ships an experimental integration "
- "of the Pixelated "
- "Webmail. It is not stable yet, but you can enable it to help "
- "beta-testing it. (Needs restart!)"))
+ "of Pixelated "
+ "Mail. Note: at the current state, anyone with access to "
+ "your device can read your mail without authentication, "
+ "by opening a browser pointing to http://localhost:9090 "))
webmail_enabled = self.settings.get_pixelmail_enabled()
self.ui.webmail_checkbox.setChecked(webmail_enabled)
if not HAS_PIXELATED:
diff --git a/src/leap/bitmask/gui/qt_browser.py b/src/leap/bitmask/gui/qt_browser.py
index b75bfb64..c62e7770 100644
--- a/src/leap/bitmask/gui/qt_browser.py
+++ b/src/leap/bitmask/gui/qt_browser.py
@@ -33,7 +33,7 @@ class PixelatedWindow(QtGui.QDialog):
layout.setContentsMargins(0, 0, 0, 0)
layout.addWidget(self.view)
self.setLayout(layout)
- self.setWindowTitle('Bitmask/Pixelated WebMail')
+ self.setWindowTitle('Bitmask Mail')
def load_app(self):
self.view.load(QtCore.QUrl(PIXELATED_URI))
diff --git a/src/leap/bitmask/gui/ui/preferences_email_page.ui b/src/leap/bitmask/gui/ui/preferences_email_page.ui
index 22d690d9..87e7121d 100644
--- a/src/leap/bitmask/gui/ui/preferences_email_page.ui
+++ b/src/leap/bitmask/gui/ui/preferences_email_page.ui
@@ -36,6 +36,32 @@
Tab 1
+
+
+
+ Bitmask Mail Configuration
+
+
+
+
+
+ Enable Bitmask Mail (needs restart)
+
+
+
+
+
+
+ webmail info
+
+
+ true
+
+
+
+
+
+
@@ -64,7 +90,7 @@
- Mail Client Configuration
+ Other Mail Clients Configuration
@@ -332,32 +358,6 @@
-
-
-
- Webmail Configuration
-
-
-
-
-
- Enable Bitmask Webmail (beta)
-
-
-
-
-
-
- webmail info
-
-
- true
-
-
-
-
-
-
--
cgit v1.2.3
From dd31801ba7361271001a81a53b0ba688375be419 Mon Sep 17 00:00:00 2001
From: Kali Kaneko
Date: Mon, 25 Apr 2016 17:26:09 -0400
Subject: [docs] bury the history in docs folder
---
HISTORY.rst | 870 -------------------------------------------------------
docs/HISTORY.rst | 870 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 870 insertions(+), 870 deletions(-)
delete mode 100644 HISTORY.rst
create mode 100644 docs/HISTORY.rst
diff --git a/HISTORY.rst b/HISTORY.rst
deleted file mode 100644
index ba0df9ef..00000000
--- a/HISTORY.rst
+++ /dev/null
@@ -1,870 +0,0 @@
-.. :history::
-
-History
--------
-
-====
-2015
-====
-
-0.9.1 November 03 - "the day of the calaca"
-+++++++++++++++++++++++++++++++++++++++++++
-
-Features
-~~~~~~~~
-- `#7542 `_: Pin mail.bitmask.net provider. Closes feature #7542.
-
-Bugfixes
-~~~~~~~~
-- `#7563 `_: try to look for /usr/bin/gpg1
-- `#7562 `_: use zmq embedded minitornado, instead of system lib.
-
-0.9.0 October 28
-++++++++++++++++
-
-Features
-~~~~~~~~
-
-- `#4284 `_: Download specific smtp certificate from provider, instead of using the vpn one.
-- `#5526 `_: Make "check" button selected by default.
-- `#6359 `_: Adapt bitmask to the new events api on leap.common.
-- `#6360 `_: Use txzmq in backend.
-- `#6368 `_: Add support to the new async-api of keymanager.
-- `#6683 `_: Add ability to generate sumo tarball.
-- `#6713 `_: Add support for xfce-polkit agent.
-- `#6876 `_: Update api port for pinned riseup.
-- `#7139 `_: Use logbook zmq handler to centralize logging.
-- `#7140 `_: Implement a thread-safe zmq handler for logbook.
-- `#7141 `_: Add log handler to display colored logs on the terminal.
-- `#7142 `_: Add log handler to store logs on bitmask.log.
-- `#7143 `_: Adapt existing log filter/silencer to the new logbook handler.
-- `#7144 `_: Replace logging handler with logbook handler bitmask-wide.
-- `#7162 `_: Log LSB-release info if available.
-- `#7180 `_: Add log rotation for bitmask.log.
-- `#7184 `_: Forward twisted logs to logging and handle logging logs with logbook.
-- `#7250 `_: Enable '--danger' for stable versions.
-- `#7291 `_: Move the updater code from the launcher to the client.
-- `#7342 `_: Added apply_updates.py script for the pyinstaller bundle.
-- `#7353 `_: Add notifications of soledad sync progress to UI.
-- `#7356 `_: Allow to disable EIP component on build.
-- `#7414 `_: Remove taskthread dependency, replace with custom (and small) code.
-- `#7419 `_: Load credentials from environment variables and trigger login.
-- `#7471 `_: Disable email firewall if we are running inside a docker container.
-- Add support to the new async-api of soledad
-
-Bugfixes
-~~~~~~~~
-
-- `#6418 `_: Cannot change preseeded providers if checks for one fail.
-- `#6424 `_: Do not disable autostart if the quit is triggered by a system logout.
-- `#6536 `_, `#6568 `_, `#6691 `_: Refactor soledad sync to do it the twisted way.
-- `#6541 `_: Client must honor the ports specified in eip-service.json.
-- `#6594 `_: Handle disabled registration on provider.
-- `#6654 `_: Regression fix, login attempt is made against previously selected provider.
-- `#6682 `_: Handle user cancel keyring open operation, this prevents a bitmask freeze.
-- `#6894 `_: Change 'ip' command location to support Fedora/RHEL distros.
-- `#7093 `_: Fix controller attribute error.
-- `#7126 `_: Don't run the event server on the backend for the standalone bundle since the launcher takes care of that.
-- `#7149 `_: Start the events server when reactor is running.
-- `#7185 `_: Log contains exported PGP Private Key.
-- `#7222 `_: Run the zmq log subscriber in the background to avoid hitting the zmq's buffer limits.
-- `#7273 `_: Logbook subscriber stop fails if not started.
-- `#7273 `_: ZMQError: address already in use - logbook subscriber already started.
-- `#7281 `_: Support a provider not providing location for the eip gateways.
-- `#7319 `_: Raise the maxfiles limit in OSX
-- `#7343 `_: Clean up and fix the tests.
-- `#7415 `_: Fix wrong argument number on window raise event.
-- `#7448 `_: Fix hangs during logout.
-- `#7451 `_: Assign the timeout 'call later' before starting the sync to prevent race conditions.
-- `#7453 `_: After a complete sync show the user the amount of unread emails.
-- `#7470 `_: Fix bug with password change.
-- `#7474 `_: Track soledad ready state on a shared place for easy access. Enable password change window.
-- `#7503 `_: Handle soledad init fail after several retries.
-- `#7512 `_: Pass on standalone flag to common.
-- `#7512 `_: Store logs in the right place.
-- `#7512 `_: Store zmq certs in the right path.
-- Authenticate properly logout calls to API.
-- Fix soledad bootstrap sync retries.
-- Fix the bootstrap script for developers so it works on Fedora/RHEL systems where there is /usr/lib64 for python libs.
-- Remove bubble argument from the logbook NullHandler
-
-0.8.1 February 25
-+++++++++++++++++
-
-Features
-~~~~~~~~
-- `#6646 `_: Gracefully fall back to ZMQ ipc sockets with restricted access if CurveZMQ is not available.
-- `#6717 `_: Split changes log into changelog and history.
-
-Bugfixes
-~~~~~~~~
-- `#6654 `_: Regression fix, login attempt is made against previously selected provider.
-- `#6058 `_: Support 'nobody' (used on Arch) as well as 'nogroup' as group names.
-
-0.8.0 January 04 -- "Charlie and the code refactory"
-++++++++++++++++++++++++++++++++++++++++++++++++++++
-
-Features
-~~~~~~~~
-- #5873: Allow frontend and backend to be run separately.
-- Refactor login widgets/logic.
-- Improved changelog :).
-
-Bugfixes
-~~~~~~~~
-- #6058: Support 'nobody' (used on Arch) as well as 'nogroup' as group names.
-- #6123: Forward the right environment data to subprocess call.
-- #6150: Do not allow Bitmask to start if there is no polkit agent running.
-- #6631: Fix failing tests.
-- #6638: Fix set initialization to support python 2.6.
-- #6652: Fix regression: polkit agent is not automatically launched.
-- #6654: Login attempt is made against previously selected provider.
-- Create zmq certificates if they don't exist.
-- Disable '--offline' flag temporarily.
-- Make pkg/tuf/release.py handle removals in the repo.
-- Reduce the wait for running threads timeout on quit.
-
-====
-2014
-====
-
-0.7.0 December 12 -- the "One window to rule them all, and in the darkness bind them." release:
-+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
-
-- Select current provider on EIP preferences. Closes #5815.
-- Handle logout correctly when we stop_services to launch the
- wizard. Related to #5815.
-- Properly remove /tmp/bitmask.lock. Closes #5866.
-- Hide EIP Start button and display correct warning on missing helpers
- files. Closes #5945.
-- Save default provider if changed on the combo box. Closes #5995.
-- Update the EIP status on provider change. Closes #5996.
-- Update and get ready to start a provider on change. Closes #5997.
-- Use python2 to run bitmask-root to work fine on systems with python3
- as default. Closes #6048.
-- Use python2.7 in bitmask-root shebang since is the common name for
- python 2 in Ubuntu, Debian, Arch. Related to #6048.
-- Remove dict comprenension in util, for 2.6 compat.
-- Login shall not wait for eip to finish if eip is not able to
- start. Closes #5994
-- Properly send the token for querying the EIP certificate. Fixes
- #6060.
-- Code cleanup and logging improvements.
-- Add email firewall blocking other users to access bitmask imap &
- smtp. Closes #6040
-- Remove the Advanced Key Management since we don't support stable
- mail yet. Closes #6087.
-- Single combined preferences window. Closes #4704, #4119, #5885.
-- Fix soledad imports (#5989).
-- Make pkg/tuf/release.py handle removals in the repo
-- Remove instructions/references of mail from the client. Closes #6140.
-- Add support for the internal LXDE polkit agent. Closes #6043.
-- Allow the server to set a custom --fragment openvpn option (#5933)
-- Add Calyx.net as pinned provider. Closes #6518.
-
-0.6.1 August 15 -- the "knock knock knocking on beta's door" release:
-+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
-
-- Add checks to ensure that the backend is alive or notify the
- user. Related to #5873.
-- Stop the backend if the frontend process does not exist any more and
- backend is not a daemon. Related to #5873.
-- Add autostart on Linux. Closes #4989.
-- Pressing ESC on 'install helper files' defaults to No. Closes #5819.
-- Replace twisted thread with QThread and get pastebin send
- working. Closes #5949.
-- Wait until EIP is up to autologin. Closes #5939
-- Fix the handling of vpn launcher errors in the UI. Closes: #5955
-- Fix logger window blocking the bitmask quit().
-- Set the standalone value for BaseConfig according to the global
- flags.
-- Improve Hide and Show Window behavior on Ubuntu. Fixes #5511.
-- Use smaller height on the window so it fits better on smaller
- resolutions. Closes #5722.
-- Disable daemon mode when we run the backend so we can spawn child
- processes on it.
-- Restrict access to the zmq certificates folder.
-- Stop the services if the selected provider is changed. Related to
- #4704. Closes #5912, #5554.
-- Minor adjustments to the layout of UI elements. Fixes #5514, #5515,
- #5510.
-- Moved provider selection dropdown menu to be at the top of the main
- windowUse same user/password restrictions as in the webapp. Closes
- #5894.
-
-0.6.0 July 18 -- the "nothing to see here" release:
-+++++++++++++++++++++++++++++++++++++++++++++++++++
-
-- Initial sync message is confusing. Closes #5875.
-- Use preferred provider on first run. Closes #5813.
-- Add TUF init repository and release tools. Closes #5864.
-- Add support for fingerprint-gui's polkit agent. Closes #5880.
-- Reroute DNS packets instead of blocking them, eliminating need to
- muck around with resolv.conf. Closes #4633, #5655, #5738, #4823
-- Use inline decrypting for initial soledad syncrhonization, to wait
- for secrets.
-- Add the ability to create an osx bundle with py2app. Closes #5845.
-- Split frontend/backend in different files. Closes #5719.
-- Implement ZMQ based messaging system. Closes #5733.
-- Launch the backend in a different process than the app. Closes
- #5734.
-
-0.5.3 June 27 -- the "encrypt ALL THE THINGS" release:
-++++++++++++++++++++++++++++++++++++++++++++++++++++++
-
-- Disable EIP if the helper files were not installed. Closes #5818.
-- Install helpers to /usr/local for bundle. Closes #5741.
-- Improve how pinned providers are handled by hardcoding it instead of
- expecting them to be in the config. Closes #4733.
-- Remove deprecated policy files. Closes #5651.
-- Install helper files only if standalone=True. Related to #5625
-- Use installer helper from within bundle path. Related to #5634
-- Pin Riseup as a provider. Closes #5783.
-- Update the bundled binaries to their path if their sha256 is not
- correct. Closes #5759.
-- Use a dict instead an object to ease later serialization of
- ProviderConfig.
-
-0.5.2 June 6 -- the "are we there yet" release:
-+++++++++++++++++++++++++++++++++++++++++++++++
-
-- Unblock local multicast IPs from linux firewall, to allow SSDP and
- Bonjour/mDNS to work.
-- Add support for gnome-shell polkit agent. Closes #4144, #4218.
-- Update username regex to support the same as webapp. Closes #5965.
-- Wrong error message for username too short. Fixes #5697.
-- Cleanup and refactor username/password validators.
-- Fix EIP autostart failing. Closes #5721.
-- Block ipv6 traffic for the moment. Closes #5693
-- Fix bug with ipv6 blocking that caused block to not get removed from
- firewall when Bitmask quit.
-- Bring firewall down when switching EIP off. Closes #5687
-- Add OPENVPN_BIN_PATH for OSX so that EIP starts properly.
-- Allow usernames to end in a digit.
-- Improve signal handling in the mainwindow and wizard.
-- Enable UI when OpenVPN bin is not found, plus check before starting
- EIP. Fixes #5619.
-- Properly set the userid for SMTP.
-- Update EIP UI if it fails to download the config.
-- Make use of cmdline in psutil backwards-compatible. Closes #5689
-- Add versioning support to bitmask-root.
-- Show flag of country for eip exit node, if available. Related #1232
-- Fix nameserver restoring. Closes #5692
-- Warn user if resolvconf cannot be found.
-- Refactor Keymanager to backend. Closes #5711.
-- Cleanup backend from hacks. Closes #5698.
-- Improve wait and quit process.
-- Move soledad password change to backend.
-- Move Mail logic to backend.
-- Separate imap/smtp logic from conductor.
-- Refactor SoledadBootstrapper to backend. Closes #5481.
-
-0.5.1 May 16 -- the "lil less leaky" release:
-+++++++++++++++++++++++++++++++++++++++++++++
-
-- Use non blocking dialog so the Pastebin result does not block the
- app. Closes #5404.
-- Handle provider setup problems and show an error to the user. Closes
- #5424.
-- Disable providers combo box during check and enable combo or line
- edit depending on radio button. Closes #5495.
-- Hide the bandwidth widget and update status icon if the openvpn
- process is killed. Closes #5497.
-- Change password doesn't work. Closes #5540.
-- Hide services that the current logged in provider does not
- have. Closes #5550.
-- If we don't have a provider supporting that service we hide the
- actions along with the widgets. Related to #5550.
-- Client mistakenly says that traffic is routed in the clear. Closes
- #5551.
-- Avoid user getting errors if he does a 'ctrl-c' on the wizard during
- the first run. Closes #5559.
-- Download/upload rates were displayed backwards in the widget
- rate. Closes #5563.
-- Fix unable to login issue. Closes #5581.
-- Hardcode paths for openvpn if STANDALONE=True. Related: #5592
-- Increase waiting time to wait for polkit agent to be up. Closes:
- #5595
-- Use openvpn hard restart. Closes: #5669
-- Enable Turn ON button for EIP whenever possible (json and cert are
- in place). Fixes #5665, #5666.
-- Fix Logout button bottom margin. Fixes #4987.
-- Properly finish the Qt app before stopping the reactor.
-- Let OpenVPN run its course when a ping-restart happens. Fixes #5564.
-- Refactor smtp logic into its bootstrapper.
-- Add flag to allow the user to start the app hidden in the
- tray. Closes #4990.
-- Refactor: move SRPAuth to the backend. Closes #5347.
-- Refactor: move EIP to backend. Closes #5349.
-- Use PySide @Slot decorator instead of 'SLOT' docstring. Closes
- #5506.
-- Advanced key management: show a note to the user if the provider
- does not support Encrypted Email. Closes #5513.
-- Gracefully handle SIGTERM, with addSystemEventTrigger twisted
- reactor's method. Closes #5672.
-- Hide the main window on quit as first thing and show a tooltip to
- inform that we are closing.
-- Increase expiration life of a pastebin log from 1 week to 1 month.
-- Use iptables firewall. Closes: #5588
-- Refactor Soledad initialization retries to SoledadBootstrapper.
-- Refactor EIPBootstrapper to the backend. Closes #5348.
-- Add flag to skip provider checks in wizard (only for testing).
-- Add support for Mate's polkit agent.
-
-0.5.0 Apr 4 -- the "Long time no see" release:
-++++++++++++++++++++++++++++++++++++++++++++++
-- Fix logging out typo, closes #4815.
-- Improve logout action, related to #5131.
-- In case of soledad bootstrap error (e.g.: network failure), re run
- all the setup process.
-- Correct resolvconf usage. Avoids permanent break of
- resolv.conf. Closes #4633.
-- Disable and stop EIP when you set EIP as disabled in the preferences
- dialog. Closes #4670.
-- Advanced Key Management: add view for stored public keys. Closes
- #4734.
-- Reset registration error and input widgets if the user goes back to
- provider selection in wizard. Closes #4742.
-- Disconnect signals before closing the wizard. Closes #4817.
-- Fix logout error message, display it similarly to other errors in
- the app. Closes #4942.
-- Client should say 1 unread email, not emails. Closes #4952.
-- Update menu name in Wizard. Closes #4984.
-- Config help menu: do not use an empty password. Closes #4985.
-- Handle wizard close correctly. Closes #4986.
-- Fix "Something went wrong with the logout" misleading error in every
- logout. Closes #4995 and #5071.
-- Use version checks in the wizard when the user choose to use an
- existing provider. Closes #5048.
-- Move error messages from srpauth to the GUI and refactor
- signals. Closes #5219.
-- Fix psutil version to avoid conflicts with gnupg required
- version. Closes #5309.
-- Update bitmask url in PKG-INFO. Closes #5395.
-- Disable 'next' button if the checks passed but the provider is
- changed. Closes #5396.
-- Do not start soledad and mail if the mail service is
- disabled. Closes #5411.
-- Don't escape logs for pastebin. Closes #5433.
-- Handle closed Soledad database on quit, speedup exit. Closes #5130.
-- Catch shutdown errors. Closes: #5313
-- Properly reset imap session on logout. Closes: #4925
-- Sync Soledad before bootstrapping mail only if the key for the user
- is not found locally. Otherwise, defer to thread and
- continue. Closes #5083.
-- Set as selected default for the eip preferences window the item
- selented in the bitmask main window. Closes #5153.
-- Cancel login does not work or needs to be pressed twice. Closes
- #4869, #4973.
-- Fail gracefully against keyring import errors.
-- Update requirements and code for the new psutil version.
-- Use Bitmask icon instead of LEAP's for the super user dialog in
- OSX. Fixes #4273.
-- Workaround a bug in Ubuntu where the menu is not displayed in the
- global menu bar. Fixes #5420.
-- Wizard: select by default the use of an existing provider if we have
- configured at least one. Closes #4488.
-- Add in-app indication of how to connect to local imap and
- smtp. Closes #4530.
-- Warn the user on incompatible api error.
-- Warn the user if is using an old app version. Closes #4636.
-- Minor UI changes: re-arrange main window so that the login widget is
- at the top and preferences are available under the menu.
-- Disable Advanced Key Manager import feature since it's experimental
- and may cause data loss. Closes #4877.
-- Offline mode for debugging. Closes: #4943
-- Add pastebin button to upload logs from the logs window to ease bug
- report. Closes #5163.
-- Add support for self signed certs. Closes #5391.
-- Add hotkey for the Help menu. Closes #5401.
-- Add --repair-mailboxes command line option. It will be needed to
- migrate existing account after a data schema changes, like it will
- be happening for 0.5.0. Closes #4792.
-- Make first Soledad sync wait for EIP to come up after logging in.
- Fixes #4885.
-- Ensure IMAP flushes data to disk before quitting. Closes #5095.
-- Update key manager auth to interact with webapp v2. Fixes #5120.
-- Handle invalid auth tokens when syncing Soledad, and show an error
- on the GUI. Fixes #5191.
-- After connecting EIP check for DNS resolution and warn the user on
- error. Closes #5301.
-- Display domain for provider the user has just logged in. Fixes
- #4631.
-- Add ability to import a maildir into a local mailbox.
-- Add ability to write mail logs to a separate file.
-- Show hash info in About bitmask (for debian versions).
-- Add the appname in the reported version string.
-- Move/refactor SRPRegister to the backend.
-- Add ability to nice application via environment variable.
-- Refactor ProviderBootstrapper out of the UI modules to a Backend
- module, obscuring all the details.
-- Remove qt4reactor as a dependency.
-
-====
-2013
-====
-
-0.3.8 Dec 6 -- the "Three week child" release:
-+++++++++++++++++++++++++++++++++++++++++++++++
-- Make the preferences window selects the current selected provider in
- the login widget even if the user is not logged in. Closes #4490.
-- Support non-ascii characters in a provider name. Closes #4952.
-- Disable Turn On EIP in tray if the service is disabled. Closes #4630.
-- Do not show the generic message "EIP has stopped" since it's
- redundant. Fixes #4632.
-- Avoid attempt to install policykit file in debian package. Closes:
- #4404
-- Properly close Soledad at quit time. Fixes #4504.
-- Fix soledad bootstrap subtasks order. Closes #4537.
-- Add --nobind as a VPN parameter to prevent binding on local
- addresses. Fixes #4543.
-- Disable Turn On EIP until we have an usable provider. Closes #4523.
-- Load provider if the wizard was rejected and the setup was
- completed.
-- Disable Turn On EIP if the "Encrypted Internet" service is disabled.
- Closes #4555.
-- If EIP service is disabled display 'Disabled' instead of 'You need
- to login to use Encrypted Internet'.
-- Disable eip-config until we have configured the provider. Closes
- #4422.
-
-0.3.7 Nov 15 -- the "The Big Lebowsky" release:
-+++++++++++++++++++++++++++++++++++++++++++++++
-- Use custom SysTray in order to display per-service tooltip easily.
- Closes #3998.
-- Escape logs with html contents so they get displayed in plaintext
- on the log viewer. Closes #4146.
-- Wizard now behaves correctly in provider selection after click
- 'cancel' or 'back'. Closes #4148.
-- Handle Timeout errors during register process. Closes #4358.
-- Send user's key to nickserver whenever keymanager is
- initialized. Closes #4364.
-- Password change dialog is now properly enabled. Closes #4449.
-- Remember provider checks in wizard, do not re-run them if the user
- goes back and forth through the wizard. Closes #3814 and #3815.
-- Improve compatibility with OSX Mavericks. Fixes #4379.
-- Initialize mail service with the userid after login, to allow
- multiple accounts. Closes: #4394
-- Give SMTP the current logged in userid. Related to #3952.
-- Do not wait for initial soledad sync to complete to launch mail
- services. Closes: #4452
-- Add hint to user about the duration of the key generation. Closes
- #3958.
-- Add advanced key management feature. Closes #4448.
-- Properly log EIP status changes.
-
-0.3.6 Nov 1 -- the "bạn có thể đọc này?" release:
-+++++++++++++++++++++++++++++++++++++++++++++++++
-
-- Fix problem changing a non-ascii password. Closes #4003.
-- Enable password change in the client only if it has started the
- correct services. Closes #4093.
-- Select the current logged in provider in the preferences
- window. Closes #4117.
-- Fix problem with non-ascii paths. Closes #4189.
-- Capture soledad boostrap errors after latest soledad changes.
-- Refactor keyring handling and make it properly save user and
- password. Fixes #4190.
-- Properly stop the imap daemon at logout. Fixes #4199.
-- Align left the speed and transferred displays for EIP. Fixes #4204.
-- Remove autostart eip option from settings panel, rely on last used
- setting. Closes #4132.
-- Add support for requests 1.1.0 (raring). Closes: #4308
-- Refactor mail connections to use state machine. Closes: #4059
-- Add a command to setup.py to freeze the versions reported under
- debian branches. Closes: #4315
-- Use coloredlogs handler if present (for development, not a
- requirement).
-- Hide the GUI for services that are not supported on the set of
- configured providers. Closes #4170.
-
-0.3.5 Oct 18 -- the "I can stand on one foot" release:
-++++++++++++++++++++++++++++++++++++++++++++++++++++++
-
-- In case of Soledad failure, display to the user that there was a
- problem. Closes #4025.
-- Widget squashing problem in wizard checking a new provider. Closes
- #4058.
-- Remember last domain used to login. Closes #4116.
-- Display first run wizard, regardless of pinned providers. Closes
- #4143.
-- Show EIP status 'ON' in the systray tooltip when is
- connected. Related to #3998.
-- Catch u1db errors during soledad initialization.
-- Disable --danger flag on release versions. Closes #4124.
-- Display mail status in the tray icon as an enabled item. Fixes
- #4036.
-- Only show N unread Emails when N > 0. Fixes #4098.
-- Hide login error message when the user interacts with the widgets
- to fix the potential problem. Fixes #4022.
-- Add call to `make` to the bootstrap script.
-- Improve GUI based on QA rounds. Fixes #4041 and #4042.
-- Increase the amount of retries for the authentication request
- session. Fixes #4037.
-- Rename EIP to Encrypted Internet in its preference panel. Fixes
- #4057.
-- Disable stdout redirection on Windows for the time being since it
- breaks the bundle.
-- Default UP_SCRIPT and DOWN_SCRIPT to None and only add that
- parameter to the vpn command if not None.
-- Look for gpg on windows with the .exe extension.
-- Change the Util menu to be named File in OSX. Fixes #4039.
-- Show more context information in the logs. Closes #3923.
-- Automate internationalization process, create project file
- dynamically on make. Closes #3925.
-- Add support for running lxde polkit agent. Closes #4028.
-- Added Vietnamese and English (United Kingdom) translations.
-- Implements openvpn observer. Closes: #3901
-- Reconnect EIP if network down. Closes #3790
-- Reconnect if tls-restart. Closes: #3262
-
-0.3.4 Oct 4 -- the "look at my new makeup" release:
-+++++++++++++++++++++++++++++++++++++++++++++++++++
-
-- Fixes a bug where you cannot login to a different provider once
- you logged in to another one. Fixes #3695.
-- Resets the session for every login attempt. Related to #3695.
-- Avoid error message if --version flag is used. Closes #3914.
-- Fix a bug in which failing to authenticate properly left
- connection in an unconsistent state. Closes: #3926
-- Avoids errors due to the EIP switch button and action being
- enabled when we do not have a configured provider. Closes: #3927
-- Add more verbose error handling during key generation and syncing.
- Helps diagnose: #3985; Addresses in part: #3965
-- Choose one gnupg binary path that is also not a symlink. Closes
- #3999.
-- Refactor vpn launchers, reuse code, improve implementations,
- update documentation. Closes #2858.
-- Add preferences option to enable/disable the automatic start of
- EIP and selection of the EIP provider to auto start. Closes #3631.
-- Force cleanlooks style for kde only if the app is running from
- bundle. Closes #3981.
-- Add a dropdown for known providers in the wizard. Closes #3995.
-- Separate pinned providers from user configures ones. Closes #3996.
-- Improve error handling during soledad bootstrap. Closes: #3965.
- Affects: #3619, #3867, #3966
-- Implement new UI design. Closes #3973.
-- Make the initial provider cert verifications against our modified
- CA-bundle (includes ca-cert certificates, for now). Closes: #3850
-- Use token header for authenticated requests. Closes #3910.
-- Do not distinguish between different possible authentication
- errors. Fixes #3859.
-- Do not start Soledad if Mail is not enabled. Fixes #3989.
-- Allow window minization on OSX. Fixes #3932.
-- Properly stop the smtp daemon. Fixes #3873.
-
-0.3.3 Sep 20 -- "the calm after the tempest" release:
-+++++++++++++++++++++++++++++++++++++++++++++++++++++
-
-- Remove execution bits in text files in bundle. Closes #3617.
-- Use generic bad username/password message instead of specific ones when
- the user uses incorrect data during login. Closes #3656.
-- Fix LoggerWindow saving more than one line return per line in the logs
- file. Closes #3714.
-- Fix keyring imports so we do not get import errors. Closes: #3759
-- Catch logout problem, display a user message and allow log back in after a
- successful logout if there was a logout error before. Closes #3774.
-- Fix path prefix helper for the bundle and add regresion tests. Closes #3778.
-- Prevent dialogs closing the app when it has been minimized to the tray. Closes #3791.
-- Do not try to install resolv-update globally. Closes: #3803
-- Inconsistent hide/show main window from tray action. Closes #3821.
-- Allow SMTP to start even when provider does not offer EIP. Closes: #3847
-- Fix username case problem at register/login. Closes #3857.
-- Catch IndexError on `first` utility.
-- Update git repo name in docs. Closes: #3417
-- Move STANDALONE flag to a module and unify get_path_prefix queries.
- Closes #3636.
-- Display the Encrypted Internet and Encrypted Email status in the systray
- tooltip. Closes #3758.
-- Tasktray menu changes, closes #3792.
-- Remove the provider domain item (e.g. bitmask.net).
-- Rename the EIP status menu items to be more descriptive.
-- Change the EIP status menu items from disabled menu items
- to submenus with children.
-- Move the EIP action menu items under the EIP status submenu tree.
-- Adds ``--version`` flag. Closes: #3816
-- Refactors EIPConnection to use LEAPConnection state machine. Closes: #3900
-- Include resource files and ui in the distrubution tarball. Closes: #3825
-
-0.3.2 Sep 6 -- the "no crashes or anything" release:
-++++++++++++++++++++++++++++++++++++++++++++++++++++
-
-- Fix up script in non-bundle linuces. Closes: #3450
-- Logout stops imap and smtp services. Closes: #3553
-- Properly daemonize polkit-gnome-authentication-agent. Closes: #3554
-- Set appropiate error on login cancel. Closes #3582.
-- Fix gateway selection problem. Closes 3595.
-- Fix typo in wizard: stablish -> establish. Closes #3615.
-- Display Encrypted Mail instead of mx in wizard. Closes #3657.
-- Fix save logs to file dialog freezing. Closes #3675.
-- Complain if setup.py is run with python3. Closes: #3711
-- Enable preferences option in systray. Closes #3717.
-- Make soledad emit failed signal for all kinds of socket error.
-- Allow to selectively silence logs from different leap components. Closes: #3504
-- Add option to select gateway manually in the preferences panel. Closes #3505.
-- Add preferences option to select the enabled services of a provider. Closes #3534.
-- Refactor basic password checks. Closes #3552.
-- Use dirspec instead of plain xdg. Closes #3574.
-- Remove last page from wizard. Closes #3616.
-- Display encrypted mail status in the tray. Closes #3659.
-
-0.3.1 Aug 23:
-+++++++++++++
-
-- Replace wizard images with the rainbow mask. Closes #3425.
-- Update leap.common minimum version needed.
-- Set the standalone flag before it's being used. Fixes #3426.
-- Stop the twisted reactor adding the stop call to the call chain
- instead of stopping it directly. Fixes #3406.
-- Allow soledad initialization to retry if it times out. Closes:
- #3413
-- Activate window when setting it visible. Also display Hide/Show
- message in the tray icon taking into account the window
- activation. Fixes #3433.
-- Do not start IMAP daemon if mail was not selected among the
- services. Fixes #3435.
-- Reword RECONNECTING state of openvpn. Fixes #3429.
-- Improve OpenVPN detection by searching for a specific leap-only
- string in the command line. This makes it possible to run other
- VPN instances while also using EIP. Fixes #3268 and #3364.
-- OSX: Check for the tun.kext existence in /Library/Extensions
- instead of /System/Library/Extensions. Fixes #3271.
-- Use DELETE /1/logout to properly logout. Fixes #3510.
-- Make the poll interval bigger to improve openvpn's internal
- behavior. If it gets queried too many times per second, it's
- behavior won't be good. Fixes #3430.
-- Transforms usernames to lower case before they are used in the
- registration and authentication. Closes #3541.
-- Add filter option to the logger window. Closes #3407.
-- Add a preference panel that lets you change your password. Closes
- #3500 #2798 #3533.
-- Move all client code into its own namespace
- (leap.bitmask). Closes: #2959
-- Make mail fetch interval in imap service configurable via
- environment variable. Closes: #3409
-- Update to new soledad package scheme (common, client and
- server). Closes #3487.
-- Fetch incoming mail when mail client logs in. Closes: #3525
-- Add first draft of the UI for Encrypted Mail. Closes #3499.
-
-0.3.0 Aug 9:
-++++++++++++
-
-- Add missing scripts does not stop if a command fails, also warns
- the user if there was an error. Closes #3294.
-- Replace 'Sign Out' with 'Log Out' and 'User' with
- 'Username'. Closes #3319.
-- Verify cacert existence before using it. Closes bug #3362.
-- Properly handle login failures. Closes bug #3401.
-- Bugfix, avoid getting negative rates. Closes #3274.
-- Raise window when setting it as visible. Fixes #3374
-- Fail gracefully when the events port 8090 is in use by something
- else. Fixes #3276.
-- Validate the username in the login form against the same regexp as
- the wizard registration form. Fixes #3214.
-- Update text from the tray menu based on the visibility of the
- window. Fixes #3400.
-- Add check for outdated polkit file. Closes #3209.
-- Add support for multiple schemas so we can support multiples api
- versions. Closes #3310.
-- Rebrand the client to be named Bitmask. Feature #3313.
-- Add cancel button to login. Closes #3318.
-- Add multiple schema support for SMTP. Closes #3403.
-- Add multiple schema support for Soledad. Closes #3404.
-- Update Transifex project name and translators'
- documentation. Closes #3418.
-- Add check for tuntap kext before launching openvpn. Closes: #2906
-- Accept flag for changing openvpn verbosity in logs. Closes: #3305
-- Add imap service to the client. Closes: #2579
-- Add pyside-uic support inside the virtualenv. This way it won't
- fail to 'make' if the virtualenv is activated. Closes #3411.
-- Reintegrate SMTP relay module. Closes #3375
-- Reintegrate Soledad into the client. Closes #3307.
-- Support bundled gpg. Related to #3397.
-- Set the default port for SMTP to be 2013.
-- Display a more generic error message in the main window, and leave
- the detailed one for the log. Closes #3373.
-
-0.2.4 Jul 26:
-+++++++++++++
-
-- Use the provider CA cert for every request once we have it
- bootstrapped (TOFU). Closes #3227.
-- Make calls to leap.common.events asynchronous. Closes #2937.
-- Always logout when closing the app if the user previously signed
- in. Fixes #3245.
-- Make sure the domain field in provider.json is escaped to avoid
- potential problems. Fixes #3244.
-- Fix incorrect handling of locks in Windows so that stalled locks
- do not avoid raising the first instance of the app. Closes: #2910
-- Use traffic rates instead of totals. Closes #2913
-- Allow to alternate between rates and total throughput for the
- virtual interface. Closes: #3232
-- Reset rates/totals when terminating connection. Closes #3249
-- Fix a bug in the displayed magnitude for the up/down traffic rates
- and totals.
-- Force Cleanlooks style if we are running in a KDE environment, so
- that it doesn't load potentially incompatible Qt libs. Fixes
- #3194.
-- Wrap long login status messages to 40 characters. Fixes #3124
-- Workaround a segmentation fault when emitting a signal with its
- last parameter being None. Fixes #3083.
-- Added IS_RELEASE_VERSION flag that allows us to use code only in
- develop versions. Closes #3224.
-- Try to terminate already running openvpn instances. Closes #2916
-- Linux: Dynamically generate policy file for polkit. Closes #3208
-- Workaround some OpenVPN problems with priviledge dropping and
- routing. Fixes #3178 #3135 #3207 #3203
-
-0.2.3 Jul 12:
-+++++++++++++
-
-- Adapt code to Soledad 0.2.1 api.
-- Fix Main Window briefly display before the wizard on first
- start. Closes Bug #2954.
-- Bugfix: Remember should not be automatically set to
- checked. Closes #2955.
-- Bugfix: reload config if switching to a different provider. Closes
- #3067.
-- Bugfix: logger window's toggle button reflects window
- state. Closes #3152.
-- Set timeout for requests to 10 seconds globally, configurable from
- leap.util.constants. Fixes #2878.
-- Bugfix: display error message on registration problem. Closes
- #3039.
-- Make wizard use the main event loop, ensuring clean termination.
-- Use cocoasudo for installing missing updown scripts.
-- Bugfix: Systray Turn ON action fails because is not correctly
- enabled/disabled. Closes #3125.
-- Bugfix: wrong systray icon on startup. Closes #3147.
-- Bugfix: parse line return in the logger window. Closes #3151.
-- Do not log user data on registration. Fixes #3168.
-- Add --log-append eip.log to windows EIP launcher options to save
- the logs in case of any problems. Fixes #2054.
-- OSX: Make the install_path relative to the launcher path instead
- -f absolute.
-- OSX: Fix icon display in cocoasudo.
-- OSX: Raise window when showing if running on OSX.
-- Bugfix: EIP status button moved to status panel.
-- Check if there is no gateway to use and display correct
- message. Close #2921.
-- Reorder tray icons according new design. Closes #2919.
-- Redirect stdout/stderr and twisted log to the logger. Closes
- #3134.
-- Improve LoggerWindow colors for easier debugging.
-- Move the key manager to its own repository/package.
-
-0.2.2 Jun 28:
-+++++++++++++
-
-- Add support for the kde polkit daemon
-- Handle 'Incorrect Password' exception (keyring)
-- Select the configured domain in the providers combo box. Closes
- #2693.
-- Remember provider along with the username and password. Closes
- #2755.
-- Close the app on rejected wizard. Closes bug #2905.
-- Only use the Keyring when it's using a known good backend. Closes
- #2960
-- Update implementation and semantics of the supported and available
- services by a provider. Closes bug #3032.
-- Only show the question mark for a check being done if the previous
- -ne passed. Fixes #2569.
-- Fix main client window not restoring after minimized into
- systray. Closes #2574
-- Set EIP different status icons depending on OS. Closes #2643.
-- Reimplement openvpn invocation to use twisted ProcessProtocol
-- Add runtime requirements checker, verifies that the requirements
- are installed and in its correct versions. Closes #2563
-- Add centraliced logging facility, log history in a window. Closes
- #2566
-- Improve wizard, hide registration widgets (labels, inputs, button)
- and only display a message. Closes #2694
-- Clarify labels through the app (use of EIP)
-- Check if the provider api version is supported. Closes feature
- #2774.
-- Autoselect VPN gateway based on timezone. Closes #2790.
-- Disable vpn disconnect on logout. Closes #2795.
-- Improve gateway selector based on timezone. It allows to use
- multiple gateways in openvpn for redundancy. Closes #2894.
-- Use cocoasudo in place of osascript for osx privilege escalation
- during openvpn launch.
-- Clicking in the tray icon will always show the context menu
- instead of activating the window under certain
- circumstances. Closes #2788
-- Autostart EIP whenever possible. Closes #2815
-- Update test suite, run_scripts and requirements to run smoothly
- with buildbot.
-- Add a copy of the processed requirements to util/
-- Display the default provider configured in the systray menu. Close
- #2813
-- Make the login steps be a chain of defers in order to be able to
- have more cancel points for the whole procedure. Closes #2571
-- Linux: check for up/down scripts and policy files and ask user for
- permission to install them in a root-writeable location. Used from
- within bundle or for broken installations.
-- Integrate SMTP-Relay into the client.
-- Integrate Soledad and KeyManager.
-- Move the KeyManager from leap.common to leap-client.
-- Only use one systray icon, repesenting the status for EIP. Closes
- #2762
-- Properly set the binary manifest to the windows openvpn
- binary. Closes #203
-- OSX: Add dialog with suggestion to install up/down scripts if
- these not found. Closes: #1264, #2759, #2249
-- Workaround for PySide breaking with multiple inheritance. Closes
- #2827
-- Refactor login to its own widget and remove Utils menu. Closes
- #2789
-- Refactor the status bits out of the MainWindow to its own
- StatusPanelWidget. Closes #2792
-- Save the default provider to be used for autostart EIP as
- DefaultProvider in leap.conf. Closes #2793
-- Cleanly terminate openvpn process, sending SIGTERM and SIGKILL
- after a while. Closes #2753
-- Use twisted's deferToThread and Deferreds to handle parallel tasks
-- Use a qt4 reactor for twisted, for launching leap twisted
- services.
-
-0.2.1 May 15:
-+++++++++++++
-
-- Rewrite most of the client based on the insight gained so far.
-- Deselecting the remember checkbox makes the app not populate
- user/password values on the login widget. Closes #2059
-- Rewording of setup steps in wizard, to make them more meaningful
- to the non-technical user. Closes #2061
-- Fix typo in wizard.
-- Fix multiple drawing of services if going back.
-- Make registration errors show in red.
-- Add a warning if EIP service needs admin password. Addresses part
- -f #2062
-- Make traffic indicators display fixed precision. Closes #2114
-- Do not hide the application if the user right clicked the system
- tray icon.
-- Sanitize network-fetched content that is used to build openvpn
- command.
-- Avoids multiple instances of leap-client. Each new one just raises
- the existing instance and quits.
-- Use dark eip icons os osx. Closes #2130
-- Moves BaseConfig to leap.common.config. Closes #2164
-- Add handling for ASSIGN_IP state from OpenVPN in the mainwindow.
-- Emit events notifying of the session_id and uid after
- authentication so other services can make use of it. Closes #1957
-- Working packaging workflow with rewritten client, using
- pyinstaller and platypus.
-- Remove network checks temporarily until we find a good way of
- doing it, and a good way to deal with them.
-- Saves the token to allow token authenticated queries.
-- Turn "leap" into namespace package, move common files to
- leap_common package that can be shared by other LEAP projects.
-- Support standalone configurations for distribution in thumbdrives
- and the like.
-- Add support for requests < 1.0.0
-- Tests infrastructure, and tests for crypto/srpauth and crypto/srpregister.
-- Documentation updated for 0.2.1 release.
-- Docstrings style changed to fit sphinx autodoc format.
-- Add a simple UI to notify of pending updates.
-- Add Windows support.
-- Try to install TAP driver on Windows if no tap device is preset.
-
diff --git a/docs/HISTORY.rst b/docs/HISTORY.rst
new file mode 100644
index 00000000..ba0df9ef
--- /dev/null
+++ b/docs/HISTORY.rst
@@ -0,0 +1,870 @@
+.. :history::
+
+History
+-------
+
+====
+2015
+====
+
+0.9.1 November 03 - "the day of the calaca"
++++++++++++++++++++++++++++++++++++++++++++
+
+Features
+~~~~~~~~
+- `#7542 `_: Pin mail.bitmask.net provider. Closes feature #7542.
+
+Bugfixes
+~~~~~~~~
+- `#7563 `_: try to look for /usr/bin/gpg1
+- `#7562 `_: use zmq embedded minitornado, instead of system lib.
+
+0.9.0 October 28
+++++++++++++++++
+
+Features
+~~~~~~~~
+
+- `#4284 `_: Download specific smtp certificate from provider, instead of using the vpn one.
+- `#5526 `_: Make "check" button selected by default.
+- `#6359 `_: Adapt bitmask to the new events api on leap.common.
+- `#6360 `_: Use txzmq in backend.
+- `#6368 `_: Add support to the new async-api of keymanager.
+- `#6683 `_: Add ability to generate sumo tarball.
+- `#6713 `_: Add support for xfce-polkit agent.
+- `#6876 `_: Update api port for pinned riseup.
+- `#7139 `_: Use logbook zmq handler to centralize logging.
+- `#7140 `_: Implement a thread-safe zmq handler for logbook.
+- `#7141 `_: Add log handler to display colored logs on the terminal.
+- `#7142 `_: Add log handler to store logs on bitmask.log.
+- `#7143 `_: Adapt existing log filter/silencer to the new logbook handler.
+- `#7144 `_: Replace logging handler with logbook handler bitmask-wide.
+- `#7162 `_: Log LSB-release info if available.
+- `#7180 `_: Add log rotation for bitmask.log.
+- `#7184 `_: Forward twisted logs to logging and handle logging logs with logbook.
+- `#7250 `_: Enable '--danger' for stable versions.
+- `#7291 `_: Move the updater code from the launcher to the client.
+- `#7342 `_: Added apply_updates.py script for the pyinstaller bundle.
+- `#7353 `_: Add notifications of soledad sync progress to UI.
+- `#7356 `_: Allow to disable EIP component on build.
+- `#7414 `_: Remove taskthread dependency, replace with custom (and small) code.
+- `#7419 `_: Load credentials from environment variables and trigger login.
+- `#7471 `_: Disable email firewall if we are running inside a docker container.
+- Add support to the new async-api of soledad
+
+Bugfixes
+~~~~~~~~
+
+- `#6418 `_: Cannot change preseeded providers if checks for one fail.
+- `#6424 `_: Do not disable autostart if the quit is triggered by a system logout.
+- `#6536 `_, `#6568 `_, `#6691 `_: Refactor soledad sync to do it the twisted way.
+- `#6541 `_: Client must honor the ports specified in eip-service.json.
+- `#6594 `_: Handle disabled registration on provider.
+- `#6654 `_: Regression fix, login attempt is made against previously selected provider.
+- `#6682 `_: Handle user cancel keyring open operation, this prevents a bitmask freeze.
+- `#6894 `_: Change 'ip' command location to support Fedora/RHEL distros.
+- `#7093 `_: Fix controller attribute error.
+- `#7126 `_: Don't run the event server on the backend for the standalone bundle since the launcher takes care of that.
+- `#7149 `_: Start the events server when reactor is running.
+- `#7185 `_: Log contains exported PGP Private Key.
+- `#7222 `_: Run the zmq log subscriber in the background to avoid hitting the zmq's buffer limits.
+- `#7273 `_: Logbook subscriber stop fails if not started.
+- `#7273 `_: ZMQError: address already in use - logbook subscriber already started.
+- `#7281 `_: Support a provider not providing location for the eip gateways.
+- `#7319 `_: Raise the maxfiles limit in OSX
+- `#7343 `_: Clean up and fix the tests.
+- `#7415 `_: Fix wrong argument number on window raise event.
+- `#7448 `_: Fix hangs during logout.
+- `#7451 `_: Assign the timeout 'call later' before starting the sync to prevent race conditions.
+- `#7453 `_: After a complete sync show the user the amount of unread emails.
+- `#7470 `_: Fix bug with password change.
+- `#7474 `_: Track soledad ready state on a shared place for easy access. Enable password change window.
+- `#7503 `_: Handle soledad init fail after several retries.
+- `#7512 `_: Pass on standalone flag to common.
+- `#7512 `_: Store logs in the right place.
+- `#7512 `_: Store zmq certs in the right path.
+- Authenticate properly logout calls to API.
+- Fix soledad bootstrap sync retries.
+- Fix the bootstrap script for developers so it works on Fedora/RHEL systems where there is /usr/lib64 for python libs.
+- Remove bubble argument from the logbook NullHandler
+
+0.8.1 February 25
++++++++++++++++++
+
+Features
+~~~~~~~~
+- `#6646 `_: Gracefully fall back to ZMQ ipc sockets with restricted access if CurveZMQ is not available.
+- `#6717 `_: Split changes log into changelog and history.
+
+Bugfixes
+~~~~~~~~
+- `#6654 `_: Regression fix, login attempt is made against previously selected provider.
+- `#6058 `_: Support 'nobody' (used on Arch) as well as 'nogroup' as group names.
+
+0.8.0 January 04 -- "Charlie and the code refactory"
+++++++++++++++++++++++++++++++++++++++++++++++++++++
+
+Features
+~~~~~~~~
+- #5873: Allow frontend and backend to be run separately.
+- Refactor login widgets/logic.
+- Improved changelog :).
+
+Bugfixes
+~~~~~~~~
+- #6058: Support 'nobody' (used on Arch) as well as 'nogroup' as group names.
+- #6123: Forward the right environment data to subprocess call.
+- #6150: Do not allow Bitmask to start if there is no polkit agent running.
+- #6631: Fix failing tests.
+- #6638: Fix set initialization to support python 2.6.
+- #6652: Fix regression: polkit agent is not automatically launched.
+- #6654: Login attempt is made against previously selected provider.
+- Create zmq certificates if they don't exist.
+- Disable '--offline' flag temporarily.
+- Make pkg/tuf/release.py handle removals in the repo.
+- Reduce the wait for running threads timeout on quit.
+
+====
+2014
+====
+
+0.7.0 December 12 -- the "One window to rule them all, and in the darkness bind them." release:
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+
+- Select current provider on EIP preferences. Closes #5815.
+- Handle logout correctly when we stop_services to launch the
+ wizard. Related to #5815.
+- Properly remove /tmp/bitmask.lock. Closes #5866.
+- Hide EIP Start button and display correct warning on missing helpers
+ files. Closes #5945.
+- Save default provider if changed on the combo box. Closes #5995.
+- Update the EIP status on provider change. Closes #5996.
+- Update and get ready to start a provider on change. Closes #5997.
+- Use python2 to run bitmask-root to work fine on systems with python3
+ as default. Closes #6048.
+- Use python2.7 in bitmask-root shebang since is the common name for
+ python 2 in Ubuntu, Debian, Arch. Related to #6048.
+- Remove dict comprenension in util, for 2.6 compat.
+- Login shall not wait for eip to finish if eip is not able to
+ start. Closes #5994
+- Properly send the token for querying the EIP certificate. Fixes
+ #6060.
+- Code cleanup and logging improvements.
+- Add email firewall blocking other users to access bitmask imap &
+ smtp. Closes #6040
+- Remove the Advanced Key Management since we don't support stable
+ mail yet. Closes #6087.
+- Single combined preferences window. Closes #4704, #4119, #5885.
+- Fix soledad imports (#5989).
+- Make pkg/tuf/release.py handle removals in the repo
+- Remove instructions/references of mail from the client. Closes #6140.
+- Add support for the internal LXDE polkit agent. Closes #6043.
+- Allow the server to set a custom --fragment openvpn option (#5933)
+- Add Calyx.net as pinned provider. Closes #6518.
+
+0.6.1 August 15 -- the "knock knock knocking on beta's door" release:
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+
+- Add checks to ensure that the backend is alive or notify the
+ user. Related to #5873.
+- Stop the backend if the frontend process does not exist any more and
+ backend is not a daemon. Related to #5873.
+- Add autostart on Linux. Closes #4989.
+- Pressing ESC on 'install helper files' defaults to No. Closes #5819.
+- Replace twisted thread with QThread and get pastebin send
+ working. Closes #5949.
+- Wait until EIP is up to autologin. Closes #5939
+- Fix the handling of vpn launcher errors in the UI. Closes: #5955
+- Fix logger window blocking the bitmask quit().
+- Set the standalone value for BaseConfig according to the global
+ flags.
+- Improve Hide and Show Window behavior on Ubuntu. Fixes #5511.
+- Use smaller height on the window so it fits better on smaller
+ resolutions. Closes #5722.
+- Disable daemon mode when we run the backend so we can spawn child
+ processes on it.
+- Restrict access to the zmq certificates folder.
+- Stop the services if the selected provider is changed. Related to
+ #4704. Closes #5912, #5554.
+- Minor adjustments to the layout of UI elements. Fixes #5514, #5515,
+ #5510.
+- Moved provider selection dropdown menu to be at the top of the main
+ windowUse same user/password restrictions as in the webapp. Closes
+ #5894.
+
+0.6.0 July 18 -- the "nothing to see here" release:
++++++++++++++++++++++++++++++++++++++++++++++++++++
+
+- Initial sync message is confusing. Closes #5875.
+- Use preferred provider on first run. Closes #5813.
+- Add TUF init repository and release tools. Closes #5864.
+- Add support for fingerprint-gui's polkit agent. Closes #5880.
+- Reroute DNS packets instead of blocking them, eliminating need to
+ muck around with resolv.conf. Closes #4633, #5655, #5738, #4823
+- Use inline decrypting for initial soledad syncrhonization, to wait
+ for secrets.
+- Add the ability to create an osx bundle with py2app. Closes #5845.
+- Split frontend/backend in different files. Closes #5719.
+- Implement ZMQ based messaging system. Closes #5733.
+- Launch the backend in a different process than the app. Closes
+ #5734.
+
+0.5.3 June 27 -- the "encrypt ALL THE THINGS" release:
+++++++++++++++++++++++++++++++++++++++++++++++++++++++
+
+- Disable EIP if the helper files were not installed. Closes #5818.
+- Install helpers to /usr/local for bundle. Closes #5741.
+- Improve how pinned providers are handled by hardcoding it instead of
+ expecting them to be in the config. Closes #4733.
+- Remove deprecated policy files. Closes #5651.
+- Install helper files only if standalone=True. Related to #5625
+- Use installer helper from within bundle path. Related to #5634
+- Pin Riseup as a provider. Closes #5783.
+- Update the bundled binaries to their path if their sha256 is not
+ correct. Closes #5759.
+- Use a dict instead an object to ease later serialization of
+ ProviderConfig.
+
+0.5.2 June 6 -- the "are we there yet" release:
++++++++++++++++++++++++++++++++++++++++++++++++
+
+- Unblock local multicast IPs from linux firewall, to allow SSDP and
+ Bonjour/mDNS to work.
+- Add support for gnome-shell polkit agent. Closes #4144, #4218.
+- Update username regex to support the same as webapp. Closes #5965.
+- Wrong error message for username too short. Fixes #5697.
+- Cleanup and refactor username/password validators.
+- Fix EIP autostart failing. Closes #5721.
+- Block ipv6 traffic for the moment. Closes #5693
+- Fix bug with ipv6 blocking that caused block to not get removed from
+ firewall when Bitmask quit.
+- Bring firewall down when switching EIP off. Closes #5687
+- Add OPENVPN_BIN_PATH for OSX so that EIP starts properly.
+- Allow usernames to end in a digit.
+- Improve signal handling in the mainwindow and wizard.
+- Enable UI when OpenVPN bin is not found, plus check before starting
+ EIP. Fixes #5619.
+- Properly set the userid for SMTP.
+- Update EIP UI if it fails to download the config.
+- Make use of cmdline in psutil backwards-compatible. Closes #5689
+- Add versioning support to bitmask-root.
+- Show flag of country for eip exit node, if available. Related #1232
+- Fix nameserver restoring. Closes #5692
+- Warn user if resolvconf cannot be found.
+- Refactor Keymanager to backend. Closes #5711.
+- Cleanup backend from hacks. Closes #5698.
+- Improve wait and quit process.
+- Move soledad password change to backend.
+- Move Mail logic to backend.
+- Separate imap/smtp logic from conductor.
+- Refactor SoledadBootstrapper to backend. Closes #5481.
+
+0.5.1 May 16 -- the "lil less leaky" release:
++++++++++++++++++++++++++++++++++++++++++++++
+
+- Use non blocking dialog so the Pastebin result does not block the
+ app. Closes #5404.
+- Handle provider setup problems and show an error to the user. Closes
+ #5424.
+- Disable providers combo box during check and enable combo or line
+ edit depending on radio button. Closes #5495.
+- Hide the bandwidth widget and update status icon if the openvpn
+ process is killed. Closes #5497.
+- Change password doesn't work. Closes #5540.
+- Hide services that the current logged in provider does not
+ have. Closes #5550.
+- If we don't have a provider supporting that service we hide the
+ actions along with the widgets. Related to #5550.
+- Client mistakenly says that traffic is routed in the clear. Closes
+ #5551.
+- Avoid user getting errors if he does a 'ctrl-c' on the wizard during
+ the first run. Closes #5559.
+- Download/upload rates were displayed backwards in the widget
+ rate. Closes #5563.
+- Fix unable to login issue. Closes #5581.
+- Hardcode paths for openvpn if STANDALONE=True. Related: #5592
+- Increase waiting time to wait for polkit agent to be up. Closes:
+ #5595
+- Use openvpn hard restart. Closes: #5669
+- Enable Turn ON button for EIP whenever possible (json and cert are
+ in place). Fixes #5665, #5666.
+- Fix Logout button bottom margin. Fixes #4987.
+- Properly finish the Qt app before stopping the reactor.
+- Let OpenVPN run its course when a ping-restart happens. Fixes #5564.
+- Refactor smtp logic into its bootstrapper.
+- Add flag to allow the user to start the app hidden in the
+ tray. Closes #4990.
+- Refactor: move SRPAuth to the backend. Closes #5347.
+- Refactor: move EIP to backend. Closes #5349.
+- Use PySide @Slot decorator instead of 'SLOT' docstring. Closes
+ #5506.
+- Advanced key management: show a note to the user if the provider
+ does not support Encrypted Email. Closes #5513.
+- Gracefully handle SIGTERM, with addSystemEventTrigger twisted
+ reactor's method. Closes #5672.
+- Hide the main window on quit as first thing and show a tooltip to
+ inform that we are closing.
+- Increase expiration life of a pastebin log from 1 week to 1 month.
+- Use iptables firewall. Closes: #5588
+- Refactor Soledad initialization retries to SoledadBootstrapper.
+- Refactor EIPBootstrapper to the backend. Closes #5348.
+- Add flag to skip provider checks in wizard (only for testing).
+- Add support for Mate's polkit agent.
+
+0.5.0 Apr 4 -- the "Long time no see" release:
+++++++++++++++++++++++++++++++++++++++++++++++
+- Fix logging out typo, closes #4815.
+- Improve logout action, related to #5131.
+- In case of soledad bootstrap error (e.g.: network failure), re run
+ all the setup process.
+- Correct resolvconf usage. Avoids permanent break of
+ resolv.conf. Closes #4633.
+- Disable and stop EIP when you set EIP as disabled in the preferences
+ dialog. Closes #4670.
+- Advanced Key Management: add view for stored public keys. Closes
+ #4734.
+- Reset registration error and input widgets if the user goes back to
+ provider selection in wizard. Closes #4742.
+- Disconnect signals before closing the wizard. Closes #4817.
+- Fix logout error message, display it similarly to other errors in
+ the app. Closes #4942.
+- Client should say 1 unread email, not emails. Closes #4952.
+- Update menu name in Wizard. Closes #4984.
+- Config help menu: do not use an empty password. Closes #4985.
+- Handle wizard close correctly. Closes #4986.
+- Fix "Something went wrong with the logout" misleading error in every
+ logout. Closes #4995 and #5071.
+- Use version checks in the wizard when the user choose to use an
+ existing provider. Closes #5048.
+- Move error messages from srpauth to the GUI and refactor
+ signals. Closes #5219.
+- Fix psutil version to avoid conflicts with gnupg required
+ version. Closes #5309.
+- Update bitmask url in PKG-INFO. Closes #5395.
+- Disable 'next' button if the checks passed but the provider is
+ changed. Closes #5396.
+- Do not start soledad and mail if the mail service is
+ disabled. Closes #5411.
+- Don't escape logs for pastebin. Closes #5433.
+- Handle closed Soledad database on quit, speedup exit. Closes #5130.
+- Catch shutdown errors. Closes: #5313
+- Properly reset imap session on logout. Closes: #4925
+- Sync Soledad before bootstrapping mail only if the key for the user
+ is not found locally. Otherwise, defer to thread and
+ continue. Closes #5083.
+- Set as selected default for the eip preferences window the item
+ selented in the bitmask main window. Closes #5153.
+- Cancel login does not work or needs to be pressed twice. Closes
+ #4869, #4973.
+- Fail gracefully against keyring import errors.
+- Update requirements and code for the new psutil version.
+- Use Bitmask icon instead of LEAP's for the super user dialog in
+ OSX. Fixes #4273.
+- Workaround a bug in Ubuntu where the menu is not displayed in the
+ global menu bar. Fixes #5420.
+- Wizard: select by default the use of an existing provider if we have
+ configured at least one. Closes #4488.
+- Add in-app indication of how to connect to local imap and
+ smtp. Closes #4530.
+- Warn the user on incompatible api error.
+- Warn the user if is using an old app version. Closes #4636.
+- Minor UI changes: re-arrange main window so that the login widget is
+ at the top and preferences are available under the menu.
+- Disable Advanced Key Manager import feature since it's experimental
+ and may cause data loss. Closes #4877.
+- Offline mode for debugging. Closes: #4943
+- Add pastebin button to upload logs from the logs window to ease bug
+ report. Closes #5163.
+- Add support for self signed certs. Closes #5391.
+- Add hotkey for the Help menu. Closes #5401.
+- Add --repair-mailboxes command line option. It will be needed to
+ migrate existing account after a data schema changes, like it will
+ be happening for 0.5.0. Closes #4792.
+- Make first Soledad sync wait for EIP to come up after logging in.
+ Fixes #4885.
+- Ensure IMAP flushes data to disk before quitting. Closes #5095.
+- Update key manager auth to interact with webapp v2. Fixes #5120.
+- Handle invalid auth tokens when syncing Soledad, and show an error
+ on the GUI. Fixes #5191.
+- After connecting EIP check for DNS resolution and warn the user on
+ error. Closes #5301.
+- Display domain for provider the user has just logged in. Fixes
+ #4631.
+- Add ability to import a maildir into a local mailbox.
+- Add ability to write mail logs to a separate file.
+- Show hash info in About bitmask (for debian versions).
+- Add the appname in the reported version string.
+- Move/refactor SRPRegister to the backend.
+- Add ability to nice application via environment variable.
+- Refactor ProviderBootstrapper out of the UI modules to a Backend
+ module, obscuring all the details.
+- Remove qt4reactor as a dependency.
+
+====
+2013
+====
+
+0.3.8 Dec 6 -- the "Three week child" release:
++++++++++++++++++++++++++++++++++++++++++++++++
+- Make the preferences window selects the current selected provider in
+ the login widget even if the user is not logged in. Closes #4490.
+- Support non-ascii characters in a provider name. Closes #4952.
+- Disable Turn On EIP in tray if the service is disabled. Closes #4630.
+- Do not show the generic message "EIP has stopped" since it's
+ redundant. Fixes #4632.
+- Avoid attempt to install policykit file in debian package. Closes:
+ #4404
+- Properly close Soledad at quit time. Fixes #4504.
+- Fix soledad bootstrap subtasks order. Closes #4537.
+- Add --nobind as a VPN parameter to prevent binding on local
+ addresses. Fixes #4543.
+- Disable Turn On EIP until we have an usable provider. Closes #4523.
+- Load provider if the wizard was rejected and the setup was
+ completed.
+- Disable Turn On EIP if the "Encrypted Internet" service is disabled.
+ Closes #4555.
+- If EIP service is disabled display 'Disabled' instead of 'You need
+ to login to use Encrypted Internet'.
+- Disable eip-config until we have configured the provider. Closes
+ #4422.
+
+0.3.7 Nov 15 -- the "The Big Lebowsky" release:
++++++++++++++++++++++++++++++++++++++++++++++++
+- Use custom SysTray in order to display per-service tooltip easily.
+ Closes #3998.
+- Escape logs with html contents so they get displayed in plaintext
+ on the log viewer. Closes #4146.
+- Wizard now behaves correctly in provider selection after click
+ 'cancel' or 'back'. Closes #4148.
+- Handle Timeout errors during register process. Closes #4358.
+- Send user's key to nickserver whenever keymanager is
+ initialized. Closes #4364.
+- Password change dialog is now properly enabled. Closes #4449.
+- Remember provider checks in wizard, do not re-run them if the user
+ goes back and forth through the wizard. Closes #3814 and #3815.
+- Improve compatibility with OSX Mavericks. Fixes #4379.
+- Initialize mail service with the userid after login, to allow
+ multiple accounts. Closes: #4394
+- Give SMTP the current logged in userid. Related to #3952.
+- Do not wait for initial soledad sync to complete to launch mail
+ services. Closes: #4452
+- Add hint to user about the duration of the key generation. Closes
+ #3958.
+- Add advanced key management feature. Closes #4448.
+- Properly log EIP status changes.
+
+0.3.6 Nov 1 -- the "bạn có thể đọc này?" release:
++++++++++++++++++++++++++++++++++++++++++++++++++
+
+- Fix problem changing a non-ascii password. Closes #4003.
+- Enable password change in the client only if it has started the
+ correct services. Closes #4093.
+- Select the current logged in provider in the preferences
+ window. Closes #4117.
+- Fix problem with non-ascii paths. Closes #4189.
+- Capture soledad boostrap errors after latest soledad changes.
+- Refactor keyring handling and make it properly save user and
+ password. Fixes #4190.
+- Properly stop the imap daemon at logout. Fixes #4199.
+- Align left the speed and transferred displays for EIP. Fixes #4204.
+- Remove autostart eip option from settings panel, rely on last used
+ setting. Closes #4132.
+- Add support for requests 1.1.0 (raring). Closes: #4308
+- Refactor mail connections to use state machine. Closes: #4059
+- Add a command to setup.py to freeze the versions reported under
+ debian branches. Closes: #4315
+- Use coloredlogs handler if present (for development, not a
+ requirement).
+- Hide the GUI for services that are not supported on the set of
+ configured providers. Closes #4170.
+
+0.3.5 Oct 18 -- the "I can stand on one foot" release:
+++++++++++++++++++++++++++++++++++++++++++++++++++++++
+
+- In case of Soledad failure, display to the user that there was a
+ problem. Closes #4025.
+- Widget squashing problem in wizard checking a new provider. Closes
+ #4058.
+- Remember last domain used to login. Closes #4116.
+- Display first run wizard, regardless of pinned providers. Closes
+ #4143.
+- Show EIP status 'ON' in the systray tooltip when is
+ connected. Related to #3998.
+- Catch u1db errors during soledad initialization.
+- Disable --danger flag on release versions. Closes #4124.
+- Display mail status in the tray icon as an enabled item. Fixes
+ #4036.
+- Only show N unread Emails when N > 0. Fixes #4098.
+- Hide login error message when the user interacts with the widgets
+ to fix the potential problem. Fixes #4022.
+- Add call to `make` to the bootstrap script.
+- Improve GUI based on QA rounds. Fixes #4041 and #4042.
+- Increase the amount of retries for the authentication request
+ session. Fixes #4037.
+- Rename EIP to Encrypted Internet in its preference panel. Fixes
+ #4057.
+- Disable stdout redirection on Windows for the time being since it
+ breaks the bundle.
+- Default UP_SCRIPT and DOWN_SCRIPT to None and only add that
+ parameter to the vpn command if not None.
+- Look for gpg on windows with the .exe extension.
+- Change the Util menu to be named File in OSX. Fixes #4039.
+- Show more context information in the logs. Closes #3923.
+- Automate internationalization process, create project file
+ dynamically on make. Closes #3925.
+- Add support for running lxde polkit agent. Closes #4028.
+- Added Vietnamese and English (United Kingdom) translations.
+- Implements openvpn observer. Closes: #3901
+- Reconnect EIP if network down. Closes #3790
+- Reconnect if tls-restart. Closes: #3262
+
+0.3.4 Oct 4 -- the "look at my new makeup" release:
++++++++++++++++++++++++++++++++++++++++++++++++++++
+
+- Fixes a bug where you cannot login to a different provider once
+ you logged in to another one. Fixes #3695.
+- Resets the session for every login attempt. Related to #3695.
+- Avoid error message if --version flag is used. Closes #3914.
+- Fix a bug in which failing to authenticate properly left
+ connection in an unconsistent state. Closes: #3926
+- Avoids errors due to the EIP switch button and action being
+ enabled when we do not have a configured provider. Closes: #3927
+- Add more verbose error handling during key generation and syncing.
+ Helps diagnose: #3985; Addresses in part: #3965
+- Choose one gnupg binary path that is also not a symlink. Closes
+ #3999.
+- Refactor vpn launchers, reuse code, improve implementations,
+ update documentation. Closes #2858.
+- Add preferences option to enable/disable the automatic start of
+ EIP and selection of the EIP provider to auto start. Closes #3631.
+- Force cleanlooks style for kde only if the app is running from
+ bundle. Closes #3981.
+- Add a dropdown for known providers in the wizard. Closes #3995.
+- Separate pinned providers from user configures ones. Closes #3996.
+- Improve error handling during soledad bootstrap. Closes: #3965.
+ Affects: #3619, #3867, #3966
+- Implement new UI design. Closes #3973.
+- Make the initial provider cert verifications against our modified
+ CA-bundle (includes ca-cert certificates, for now). Closes: #3850
+- Use token header for authenticated requests. Closes #3910.
+- Do not distinguish between different possible authentication
+ errors. Fixes #3859.
+- Do not start Soledad if Mail is not enabled. Fixes #3989.
+- Allow window minization on OSX. Fixes #3932.
+- Properly stop the smtp daemon. Fixes #3873.
+
+0.3.3 Sep 20 -- "the calm after the tempest" release:
++++++++++++++++++++++++++++++++++++++++++++++++++++++
+
+- Remove execution bits in text files in bundle. Closes #3617.
+- Use generic bad username/password message instead of specific ones when
+ the user uses incorrect data during login. Closes #3656.
+- Fix LoggerWindow saving more than one line return per line in the logs
+ file. Closes #3714.
+- Fix keyring imports so we do not get import errors. Closes: #3759
+- Catch logout problem, display a user message and allow log back in after a
+ successful logout if there was a logout error before. Closes #3774.
+- Fix path prefix helper for the bundle and add regresion tests. Closes #3778.
+- Prevent dialogs closing the app when it has been minimized to the tray. Closes #3791.
+- Do not try to install resolv-update globally. Closes: #3803
+- Inconsistent hide/show main window from tray action. Closes #3821.
+- Allow SMTP to start even when provider does not offer EIP. Closes: #3847
+- Fix username case problem at register/login. Closes #3857.
+- Catch IndexError on `first` utility.
+- Update git repo name in docs. Closes: #3417
+- Move STANDALONE flag to a module and unify get_path_prefix queries.
+ Closes #3636.
+- Display the Encrypted Internet and Encrypted Email status in the systray
+ tooltip. Closes #3758.
+- Tasktray menu changes, closes #3792.
+- Remove the provider domain item (e.g. bitmask.net).
+- Rename the EIP status menu items to be more descriptive.
+- Change the EIP status menu items from disabled menu items
+ to submenus with children.
+- Move the EIP action menu items under the EIP status submenu tree.
+- Adds ``--version`` flag. Closes: #3816
+- Refactors EIPConnection to use LEAPConnection state machine. Closes: #3900
+- Include resource files and ui in the distrubution tarball. Closes: #3825
+
+0.3.2 Sep 6 -- the "no crashes or anything" release:
+++++++++++++++++++++++++++++++++++++++++++++++++++++
+
+- Fix up script in non-bundle linuces. Closes: #3450
+- Logout stops imap and smtp services. Closes: #3553
+- Properly daemonize polkit-gnome-authentication-agent. Closes: #3554
+- Set appropiate error on login cancel. Closes #3582.
+- Fix gateway selection problem. Closes 3595.
+- Fix typo in wizard: stablish -> establish. Closes #3615.
+- Display Encrypted Mail instead of mx in wizard. Closes #3657.
+- Fix save logs to file dialog freezing. Closes #3675.
+- Complain if setup.py is run with python3. Closes: #3711
+- Enable preferences option in systray. Closes #3717.
+- Make soledad emit failed signal for all kinds of socket error.
+- Allow to selectively silence logs from different leap components. Closes: #3504
+- Add option to select gateway manually in the preferences panel. Closes #3505.
+- Add preferences option to select the enabled services of a provider. Closes #3534.
+- Refactor basic password checks. Closes #3552.
+- Use dirspec instead of plain xdg. Closes #3574.
+- Remove last page from wizard. Closes #3616.
+- Display encrypted mail status in the tray. Closes #3659.
+
+0.3.1 Aug 23:
++++++++++++++
+
+- Replace wizard images with the rainbow mask. Closes #3425.
+- Update leap.common minimum version needed.
+- Set the standalone flag before it's being used. Fixes #3426.
+- Stop the twisted reactor adding the stop call to the call chain
+ instead of stopping it directly. Fixes #3406.
+- Allow soledad initialization to retry if it times out. Closes:
+ #3413
+- Activate window when setting it visible. Also display Hide/Show
+ message in the tray icon taking into account the window
+ activation. Fixes #3433.
+- Do not start IMAP daemon if mail was not selected among the
+ services. Fixes #3435.
+- Reword RECONNECTING state of openvpn. Fixes #3429.
+- Improve OpenVPN detection by searching for a specific leap-only
+ string in the command line. This makes it possible to run other
+ VPN instances while also using EIP. Fixes #3268 and #3364.
+- OSX: Check for the tun.kext existence in /Library/Extensions
+ instead of /System/Library/Extensions. Fixes #3271.
+- Use DELETE /1/logout to properly logout. Fixes #3510.
+- Make the poll interval bigger to improve openvpn's internal
+ behavior. If it gets queried too many times per second, it's
+ behavior won't be good. Fixes #3430.
+- Transforms usernames to lower case before they are used in the
+ registration and authentication. Closes #3541.
+- Add filter option to the logger window. Closes #3407.
+- Add a preference panel that lets you change your password. Closes
+ #3500 #2798 #3533.
+- Move all client code into its own namespace
+ (leap.bitmask). Closes: #2959
+- Make mail fetch interval in imap service configurable via
+ environment variable. Closes: #3409
+- Update to new soledad package scheme (common, client and
+ server). Closes #3487.
+- Fetch incoming mail when mail client logs in. Closes: #3525
+- Add first draft of the UI for Encrypted Mail. Closes #3499.
+
+0.3.0 Aug 9:
+++++++++++++
+
+- Add missing scripts does not stop if a command fails, also warns
+ the user if there was an error. Closes #3294.
+- Replace 'Sign Out' with 'Log Out' and 'User' with
+ 'Username'. Closes #3319.
+- Verify cacert existence before using it. Closes bug #3362.
+- Properly handle login failures. Closes bug #3401.
+- Bugfix, avoid getting negative rates. Closes #3274.
+- Raise window when setting it as visible. Fixes #3374
+- Fail gracefully when the events port 8090 is in use by something
+ else. Fixes #3276.
+- Validate the username in the login form against the same regexp as
+ the wizard registration form. Fixes #3214.
+- Update text from the tray menu based on the visibility of the
+ window. Fixes #3400.
+- Add check for outdated polkit file. Closes #3209.
+- Add support for multiple schemas so we can support multiples api
+ versions. Closes #3310.
+- Rebrand the client to be named Bitmask. Feature #3313.
+- Add cancel button to login. Closes #3318.
+- Add multiple schema support for SMTP. Closes #3403.
+- Add multiple schema support for Soledad. Closes #3404.
+- Update Transifex project name and translators'
+ documentation. Closes #3418.
+- Add check for tuntap kext before launching openvpn. Closes: #2906
+- Accept flag for changing openvpn verbosity in logs. Closes: #3305
+- Add imap service to the client. Closes: #2579
+- Add pyside-uic support inside the virtualenv. This way it won't
+ fail to 'make' if the virtualenv is activated. Closes #3411.
+- Reintegrate SMTP relay module. Closes #3375
+- Reintegrate Soledad into the client. Closes #3307.
+- Support bundled gpg. Related to #3397.
+- Set the default port for SMTP to be 2013.
+- Display a more generic error message in the main window, and leave
+ the detailed one for the log. Closes #3373.
+
+0.2.4 Jul 26:
++++++++++++++
+
+- Use the provider CA cert for every request once we have it
+ bootstrapped (TOFU). Closes #3227.
+- Make calls to leap.common.events asynchronous. Closes #2937.
+- Always logout when closing the app if the user previously signed
+ in. Fixes #3245.
+- Make sure the domain field in provider.json is escaped to avoid
+ potential problems. Fixes #3244.
+- Fix incorrect handling of locks in Windows so that stalled locks
+ do not avoid raising the first instance of the app. Closes: #2910
+- Use traffic rates instead of totals. Closes #2913
+- Allow to alternate between rates and total throughput for the
+ virtual interface. Closes: #3232
+- Reset rates/totals when terminating connection. Closes #3249
+- Fix a bug in the displayed magnitude for the up/down traffic rates
+ and totals.
+- Force Cleanlooks style if we are running in a KDE environment, so
+ that it doesn't load potentially incompatible Qt libs. Fixes
+ #3194.
+- Wrap long login status messages to 40 characters. Fixes #3124
+- Workaround a segmentation fault when emitting a signal with its
+ last parameter being None. Fixes #3083.
+- Added IS_RELEASE_VERSION flag that allows us to use code only in
+ develop versions. Closes #3224.
+- Try to terminate already running openvpn instances. Closes #2916
+- Linux: Dynamically generate policy file for polkit. Closes #3208
+- Workaround some OpenVPN problems with priviledge dropping and
+ routing. Fixes #3178 #3135 #3207 #3203
+
+0.2.3 Jul 12:
++++++++++++++
+
+- Adapt code to Soledad 0.2.1 api.
+- Fix Main Window briefly display before the wizard on first
+ start. Closes Bug #2954.
+- Bugfix: Remember should not be automatically set to
+ checked. Closes #2955.
+- Bugfix: reload config if switching to a different provider. Closes
+ #3067.
+- Bugfix: logger window's toggle button reflects window
+ state. Closes #3152.
+- Set timeout for requests to 10 seconds globally, configurable from
+ leap.util.constants. Fixes #2878.
+- Bugfix: display error message on registration problem. Closes
+ #3039.
+- Make wizard use the main event loop, ensuring clean termination.
+- Use cocoasudo for installing missing updown scripts.
+- Bugfix: Systray Turn ON action fails because is not correctly
+ enabled/disabled. Closes #3125.
+- Bugfix: wrong systray icon on startup. Closes #3147.
+- Bugfix: parse line return in the logger window. Closes #3151.
+- Do not log user data on registration. Fixes #3168.
+- Add --log-append eip.log to windows EIP launcher options to save
+ the logs in case of any problems. Fixes #2054.
+- OSX: Make the install_path relative to the launcher path instead
+ -f absolute.
+- OSX: Fix icon display in cocoasudo.
+- OSX: Raise window when showing if running on OSX.
+- Bugfix: EIP status button moved to status panel.
+- Check if there is no gateway to use and display correct
+ message. Close #2921.
+- Reorder tray icons according new design. Closes #2919.
+- Redirect stdout/stderr and twisted log to the logger. Closes
+ #3134.
+- Improve LoggerWindow colors for easier debugging.
+- Move the key manager to its own repository/package.
+
+0.2.2 Jun 28:
++++++++++++++
+
+- Add support for the kde polkit daemon
+- Handle 'Incorrect Password' exception (keyring)
+- Select the configured domain in the providers combo box. Closes
+ #2693.
+- Remember provider along with the username and password. Closes
+ #2755.
+- Close the app on rejected wizard. Closes bug #2905.
+- Only use the Keyring when it's using a known good backend. Closes
+ #2960
+- Update implementation and semantics of the supported and available
+ services by a provider. Closes bug #3032.
+- Only show the question mark for a check being done if the previous
+ -ne passed. Fixes #2569.
+- Fix main client window not restoring after minimized into
+ systray. Closes #2574
+- Set EIP different status icons depending on OS. Closes #2643.
+- Reimplement openvpn invocation to use twisted ProcessProtocol
+- Add runtime requirements checker, verifies that the requirements
+ are installed and in its correct versions. Closes #2563
+- Add centraliced logging facility, log history in a window. Closes
+ #2566
+- Improve wizard, hide registration widgets (labels, inputs, button)
+ and only display a message. Closes #2694
+- Clarify labels through the app (use of EIP)
+- Check if the provider api version is supported. Closes feature
+ #2774.
+- Autoselect VPN gateway based on timezone. Closes #2790.
+- Disable vpn disconnect on logout. Closes #2795.
+- Improve gateway selector based on timezone. It allows to use
+ multiple gateways in openvpn for redundancy. Closes #2894.
+- Use cocoasudo in place of osascript for osx privilege escalation
+ during openvpn launch.
+- Clicking in the tray icon will always show the context menu
+ instead of activating the window under certain
+ circumstances. Closes #2788
+- Autostart EIP whenever possible. Closes #2815
+- Update test suite, run_scripts and requirements to run smoothly
+ with buildbot.
+- Add a copy of the processed requirements to util/
+- Display the default provider configured in the systray menu. Close
+ #2813
+- Make the login steps be a chain of defers in order to be able to
+ have more cancel points for the whole procedure. Closes #2571
+- Linux: check for up/down scripts and policy files and ask user for
+ permission to install them in a root-writeable location. Used from
+ within bundle or for broken installations.
+- Integrate SMTP-Relay into the client.
+- Integrate Soledad and KeyManager.
+- Move the KeyManager from leap.common to leap-client.
+- Only use one systray icon, repesenting the status for EIP. Closes
+ #2762
+- Properly set the binary manifest to the windows openvpn
+ binary. Closes #203
+- OSX: Add dialog with suggestion to install up/down scripts if
+ these not found. Closes: #1264, #2759, #2249
+- Workaround for PySide breaking with multiple inheritance. Closes
+ #2827
+- Refactor login to its own widget and remove Utils menu. Closes
+ #2789
+- Refactor the status bits out of the MainWindow to its own
+ StatusPanelWidget. Closes #2792
+- Save the default provider to be used for autostart EIP as
+ DefaultProvider in leap.conf. Closes #2793
+- Cleanly terminate openvpn process, sending SIGTERM and SIGKILL
+ after a while. Closes #2753
+- Use twisted's deferToThread and Deferreds to handle parallel tasks
+- Use a qt4 reactor for twisted, for launching leap twisted
+ services.
+
+0.2.1 May 15:
++++++++++++++
+
+- Rewrite most of the client based on the insight gained so far.
+- Deselecting the remember checkbox makes the app not populate
+ user/password values on the login widget. Closes #2059
+- Rewording of setup steps in wizard, to make them more meaningful
+ to the non-technical user. Closes #2061
+- Fix typo in wizard.
+- Fix multiple drawing of services if going back.
+- Make registration errors show in red.
+- Add a warning if EIP service needs admin password. Addresses part
+ -f #2062
+- Make traffic indicators display fixed precision. Closes #2114
+- Do not hide the application if the user right clicked the system
+ tray icon.
+- Sanitize network-fetched content that is used to build openvpn
+ command.
+- Avoids multiple instances of leap-client. Each new one just raises
+ the existing instance and quits.
+- Use dark eip icons os osx. Closes #2130
+- Moves BaseConfig to leap.common.config. Closes #2164
+- Add handling for ASSIGN_IP state from OpenVPN in the mainwindow.
+- Emit events notifying of the session_id and uid after
+ authentication so other services can make use of it. Closes #1957
+- Working packaging workflow with rewritten client, using
+ pyinstaller and platypus.
+- Remove network checks temporarily until we find a good way of
+ doing it, and a good way to deal with them.
+- Saves the token to allow token authenticated queries.
+- Turn "leap" into namespace package, move common files to
+ leap_common package that can be shared by other LEAP projects.
+- Support standalone configurations for distribution in thumbdrives
+ and the like.
+- Add support for requests < 1.0.0
+- Tests infrastructure, and tests for crypto/srpauth and crypto/srpregister.
+- Documentation updated for 0.2.1 release.
+- Docstrings style changed to fit sphinx autodoc format.
+- Add a simple UI to notify of pending updates.
+- Add Windows support.
+- Try to install TAP driver on Windows if no tap device is preset.
+
--
cgit v1.2.3
From 4c9074d27f25db6069721eb3cac35bafe53b7c48 Mon Sep 17 00:00:00 2001
From: Kali Kaneko
Date: Mon, 25 Apr 2016 17:26:30 -0400
Subject: [pkg] remove the run_tests script
---
run_tests.sh | 172 -----------------------------------------------------------
1 file changed, 172 deletions(-)
delete mode 100755 run_tests.sh
diff --git a/run_tests.sh b/run_tests.sh
deleted file mode 100755
index 0d7e7463..00000000
--- a/run_tests.sh
+++ /dev/null
@@ -1,172 +0,0 @@
-#!/bin/bash
-
-set -e
-
-function usage {
- echo "Usage: $0 [OPTION]...[@virtualenv-name]"
- echo "Run leap-client test suite"
- echo ""
- echo " -V, --virtual-env Always use virtualenv. Install automatically if not present"
- echo " -N, --no-virtual-env Don't use virtualenv. Run tests in local environment"
- echo " -s, --no-site-packages Isolate the virtualenv from the global Python environment"
- echo " -x, --stop Stop running tests after the first error or failure."
- echo " -f, --force Force a clean re-build of the virtual environment. Useful when dependencies have been added."
- echo " -p, --pep8 Just run pep8"
- echo " -P, --no-pep8 Don't run pep8"
- echo " -c, --coverage Generate coverage report"
- echo " -h, --help Print this usage message"
- echo " -A, --all Run all tests, without excluding any"
- echo " -i, --progressive Run with nose-progressive plugin"
- echo " --hide-elapsed Don't print the elapsed time for each test along with slow test list"
- echo ""
- echo "Note: with no options specified, the script will try to run the tests in a virtual environment,"
- echo " If no virtualenv is found, the script will ask if you would like to create one. If you "
- echo " prefer to run tests NOT in a virtual environment, simply pass the -N option."
- echo " If you pass @virtualenv-name, the given virtualenv will be used as long as "
- echo " virtualenvwrapper.sh can be found in the PATH."
- exit
-}
-
-function process_option {
- case "$1" in
- -h|--help) usage;;
- -V|--virtual-env) always_venv=1; never_venv=0;;
- -N|--no-virtual-env) always_venv=0; never_venv=1;;
- -s|--no-site-packages) no_site_packages=1;;
- -f|--force) force=1;;
- -p|--pep8) just_pep8=1;;
- -P|--no-pep8) no_pep8=1;;
- -c|--coverage) coverage=1;;
- -A|--all) alltests=1;;
- -i|--progressive) progressive=1;;
- @*) venvwrapper=1; source_venv=`echo $1 | cut -c 2-`;;
- -*) noseopts="$noseopts $1";;
- *) noseargs="$noseargs $1"
- esac
-}
-
-venv=.venv
-with_venv=pkg/tools/with_venv.sh
-with_venvwrapper=pkg/tools/with_venvwrapper.sh
-always_venv=0
-never_venv=0
-force=0
-no_site_packages=0
-installvenvopts=
-noseargs=
-noseopts=
-venvwrapper=0
-source_venv=
-wrapper=""
-just_pep8=0
-no_pep8=0
-coverage=0
-alltests=0
-progressive=0
-
-for arg in "$@"; do
- process_option $arg
-done
-
-# If enabled, tell nose to collect coverage data
-if [ $coverage -eq 1 ]; then
- noseopts="$noseopts --with-coverage --cover-package=leap --cover-html --cover-html-dir=docs/covhtml/ --cover-erase"
-fi
-
-if [ $no_site_packages -eq 1 ]; then
- installvenvopts="--no-site-packages"
-fi
-
-# If alltests flag is not set, let's exclude some dirs that are troublesome.
-if [ $alltests -eq 0 ]; then
- echo "[+] Running ALL tests..."
- #noseopts="$noseopts --exclude-dir=leap/soledad"
-fi
-
-# If progressive flag enabled, run with this nice plugin :)
-if [ $progressive -eq 1 ]; then
- noseopts="$noseopts --with-progressive"
-fi
-
-function run_tests {
- echo "running tests..."
-
- if [ $venvwrapper -eq 1 ]; then
- VIRTUAL_ENV=$WORKON_HOME/$source_venv
- wrapper="$with_venvwrapper $source_venv"
-
- fi
-
- #NOSETESTS="nosetests leap --exclude=soledad* $noseopts $noseargs"
- NOSETESTS="$VIRTUAL_ENV/bin/nosetests . $noseopts $noseargs"
- #--with-coverage --cover-package=leap"
-
- # Just run the test suites in current environment
- echo "NOSETESTS=$NOSETESTS"
- ${wrapper} $NOSETESTS
- # If we get some short import error right away, print the error log directly
- RESULT=$?
- return $RESULT
-}
-
-function run_pep8 {
- echo "Running pep8 ..."
- srcfiles="src/leap"
- # Just run PEP8 in current environment
- ${wrapper} flake8 ${pep8_opts} ${srcfiles}
-}
-
-# XXX we cannot run tests that need X server
-# in the current debhelper build process,
-# so I exclude the topmost tests
-
-
-if [ $never_venv -eq 0 ]
-then
- # Remove the virtual environment if --force used
- if [ $force -eq 1 ]; then
- echo "Cleaning virtualenv..."
- rm -rf ${venv}
- fi
- if [ -e ${venv} ]; then
- wrapper="${with_venv}"
- else
- if [ $always_venv -eq 1 ]; then
- # Automatically install the virtualenv
- python pkg/install_venv.py $installvenvopts
- wrapper="${with_venv}"
- else
- echo -e "No virtual environment found...create one? (Y/n) \c"
- read use_ve
- if [ "x$use_ve" = "xY" -o "x$use_ve" = "x" -o "x$use_ve" = "xy" ]; then
- # Install the virtualenv and run the test suite in it
- python pkg/install_venv.py $installvenvopts
- wrapper=${with_venv}
- fi
- fi
- fi
-fi
-
-# Delete old coverage data from previous runs
-if [ $coverage -eq 1 ]; then
- ${wrapper} coverage erase
-fi
-
-if [ $just_pep8 -eq 1 ]; then
- run_pep8
- exit
-fi
-
-run_tests
-
-if [ -z "$noseargs" ]; then
- if [ $no_pep8 -eq 0 ]; then
- run_pep8
- fi
-fi
-
-if [ $coverage -eq 1 ]; then
- echo "Generating coverage report in docs/covhtml/"
- echo "now point your browser at docs/covhtml/index.html"
- exit
-fi
--
cgit v1.2.3
From 2f7773d2985fa5aa3c0cadb0935cd6b557a35a4c Mon Sep 17 00:00:00 2001
From: Kali Kaneko
Date: Mon, 25 Apr 2016 17:27:04 -0400
Subject: [tests] remove tox config file
---
tox.ini | 12 ------------
1 file changed, 12 deletions(-)
delete mode 100644 tox.ini
diff --git a/tox.ini b/tox.ini
deleted file mode 100644
index e041515d..00000000
--- a/tox.ini
+++ /dev/null
@@ -1,12 +0,0 @@
-[tox]
-envlist = py26,py27
-
-[testenv]
-deps = -r{toxinidir}/pkg/requirements.pip
- -r{toxinidir}/pkg/requirements-testing.pip
-sitepackages = True
-commands = xvfb-run nosetests leap --first-package-wins --exclude=soledad*
-
-[testenv:pep8]
-deps = pep8==1.1
-commands = pep8 --repeat --show-source src/leap setup.py --ignore=E202,W602 --exclude=*_rc.py --repeat
--
cgit v1.2.3
From f47416804ad2f88ba27aa032e0d2fc1c9fd314c8 Mon Sep 17 00:00:00 2001
From: Kali Kaneko
Date: Mon, 25 Apr 2016 17:30:35 -0400
Subject: [docs] add logout segfault to known issues
---
changes/next-changelog.rst | 1 +
1 file changed, 1 insertion(+)
diff --git a/changes/next-changelog.rst b/changes/next-changelog.rst
index ca74746f..8a5035ff 100644
--- a/changes/next-changelog.rst
+++ b/changes/next-changelog.rst
@@ -41,4 +41,5 @@ Misc
Known Issues
~~~~~~~~~~~~
+- `#8057 `_: Logging out twice produces a segfault in Qt
- `#1236 `_: Description of the known issue corresponding with issue #1236.
--
cgit v1.2.3
From 5a1dd49debdcd9a1ce0568217e9411d1e45a3cad Mon Sep 17 00:00:00 2001
From: Ruben Pollan
Date: Mon, 25 Apr 2016 20:24:04 -0300
Subject: [bug] represent keys correctly in preference window
---
src/leap/bitmask/backend/components.py | 10 +++++-----
src/leap/bitmask/gui/preferences_email_page.py | 6 ++++--
src/leap/bitmask/gui/ui/preferences_email_page.ui | 2 +-
3 files changed, 10 insertions(+), 8 deletions(-)
diff --git a/src/leap/bitmask/backend/components.py b/src/leap/bitmask/backend/components.py
index 3192e1c4..ba64fd65 100644
--- a/src/leap/bitmask/backend/components.py
+++ b/src/leap/bitmask/backend/components.py
@@ -994,14 +994,14 @@ class Keymanager(object):
d.addCallback(export)
d.addErrback(log_error)
+ @defer.inlineCallbacks
def list_keys(self):
"""
List all the keys stored in the local DB.
"""
- d = self._keymanager_proxy.get_all_keys()
- d.addCallback(
- lambda keys:
- self._signaler.signal(self._signaler.keymanager_keys_list, keys))
+ keys = yield self._keymanager_proxy.get_all_keys()
+ keydicts = [dict(key) for key in keys]
+ self._signaler.signal(self._signaler.keymanager_keys_list, keydicts)
def get_key_details(self, username):
"""
@@ -1009,7 +1009,7 @@ class Keymanager(object):
"""
def signal_details(public_key):
self._signaler.signal(self._signaler.keymanager_key_details,
- public_key.get_dict())
+ dict(public_key))
d = self._keymanager_proxy.get_key(username,
openpgp.OpenPGPKey)
diff --git a/src/leap/bitmask/gui/preferences_email_page.py b/src/leap/bitmask/gui/preferences_email_page.py
index f6d6f036..7186450d 100644
--- a/src/leap/bitmask/gui/preferences_email_page.py
+++ b/src/leap/bitmask/gui/preferences_email_page.py
@@ -90,6 +90,8 @@ class PreferencesEmailPage(PreferencesPage):
connect signals
"""
self.app.signaler.keymanager_key_details.connect(self._key_details)
+ self.app.signaler.keymanager_keys_list.connect(
+ self._keymanager_keys_list)
self.app.signaler.keymanager_export_ok.connect(
self._keymanager_export_ok)
self.app.signaler.keymanager_export_error.connect(
@@ -218,9 +220,9 @@ class PreferencesEmailPage(PreferencesPage):
row = self.ui.keys_table.rowCount()
self.ui.keys_table.insertRow(row)
self.ui.keys_table.setItem(
- row, 0, QtGui.QTableWidgetItem(key.address))
+ row, 0, QtGui.QTableWidgetItem(" ".join(key["uids"])))
self.ui.keys_table.setItem(
- row, 1, QtGui.QTableWidgetItem(key.fingerprint))
+ row, 1, QtGui.QTableWidgetItem(key["fingerprint"]))
def _toggle_webmail(self, state):
value = True if state == QtCore.Qt.Checked else False
diff --git a/src/leap/bitmask/gui/ui/preferences_email_page.ui b/src/leap/bitmask/gui/ui/preferences_email_page.ui
index 87e7121d..08feb7b0 100644
--- a/src/leap/bitmask/gui/ui/preferences_email_page.ui
+++ b/src/leap/bitmask/gui/ui/preferences_email_page.ui
@@ -581,7 +581,7 @@
- Key ID
+ Fingerprint
--
cgit v1.2.3
From cc4b55926d20b81a3c381dfb41cae42ab080f557 Mon Sep 17 00:00:00 2001
From: Kali Kaneko
Date: Tue, 26 Apr 2016 20:03:44 -0400
Subject: [pkg] pick cacert from the repo, not the venv
---
pkg/next-version | 2 +-
pkg/pyinst/pyinst-build.mk | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/pkg/next-version b/pkg/next-version
index 3d4f0a85..29a0f215 100644
--- a/pkg/next-version
+++ b/pkg/next-version
@@ -1 +1 @@
-0.9.2.rc1
+0.9.2.rc2
diff --git a/pkg/pyinst/pyinst-build.mk b/pkg/pyinst/pyinst-build.mk
index 92a1cbb3..664f13ec 100644
--- a/pkg/pyinst/pyinst-build.mk
+++ b/pkg/pyinst/pyinst-build.mk
@@ -22,7 +22,7 @@ reset-ver:
pyinst-hacks-linux:
# XXX this should be taken care of by pyinstaller data collector
- cp $(VIRTUAL_ENV)/lib/python2.7/site-packages/leap/common/cacert.pem $(DIST)
+ cp ../leap_common/src/leap/common/cacert.pem $(DIST)
mkdir -p $(DIST)pysqlcipher
mkdir -p $(DIST)pixelated
mkdir -p $(DIST)twisted/web
--
cgit v1.2.3
From 68096fa81eebb07165c27648ab804d9e1c695f8e Mon Sep 17 00:00:00 2001
From: Kali Kaneko
Date: Tue, 26 Apr 2016 23:07:42 -0400
Subject: [style] fix typo: Webmail -> Mail
---
src/leap/bitmask/gui/ui/mainwindow.ui | 2 +-
src/leap/bitmask/gui/ui/preferences_email_page.ui | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/leap/bitmask/gui/ui/mainwindow.ui b/src/leap/bitmask/gui/ui/mainwindow.ui
index 976c0c0a..0dd0b891 100644
--- a/src/leap/bitmask/gui/ui/mainwindow.ui
+++ b/src/leap/bitmask/gui/ui/mainwindow.ui
@@ -373,7 +373,7 @@
- Bitmask Webmail
+ Bitmask Mail
diff --git a/src/leap/bitmask/gui/ui/preferences_email_page.ui b/src/leap/bitmask/gui/ui/preferences_email_page.ui
index 87e7121d..1101d7ba 100644
--- a/src/leap/bitmask/gui/ui/preferences_email_page.ui
+++ b/src/leap/bitmask/gui/ui/preferences_email_page.ui
@@ -39,7 +39,7 @@
- Bitmask Mail Configuration
+ Bitmask Mail
--
cgit v1.2.3
From da45ed15190ea0f9c7c38b6312239f27664545a4 Mon Sep 17 00:00:00 2001
From: Kali Kaneko
Date: Thu, 28 Apr 2016 15:46:13 -0400
Subject: [bug] do not force autobahn dependency yet
websockets interface is not mature enough yet, make this dependency
optional, for the case the user actively enables it.
- Releases: 0.9.2
---
src/leap/bitmask/core/service.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/leap/bitmask/core/service.py b/src/leap/bitmask/core/service.py
index 13c8864a..ceda6353 100644
--- a/src/leap/bitmask/core/service.py
+++ b/src/leap/bitmask/core/service.py
@@ -26,7 +26,6 @@ from leap.bitmask import __version__
from leap.bitmask.core import configurable
from leap.bitmask.core import mail_services
from leap.bitmask.core import _zmq
-from leap.bitmask.core import websocket
from leap.bonafide.service import BonafideService
from leap.common.events import server as event_server
# from leap.vpn import EIPService
@@ -103,6 +102,7 @@ class BitmaskBackend(configurable.ConfigurableService):
zs.setServiceParent(self)
def init_web(self):
+ from leap.bitmask.core import websocket
ws = websocket.WebSocketsDispatcherService(self)
ws.setServiceParent(self)
--
cgit v1.2.3
From 928f547a1d1235306056be1d81e8400d4d77ecce Mon Sep 17 00:00:00 2001
From: Kali Kaneko
Date: Sat, 30 Apr 2016 12:15:16 -0400
Subject: [bug] fix hardcoded paths
---
src/leap/bitmask/core/mail_services.py | 4 ++--
src/leap/bitmask/core/service.py | 2 +-
2 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/src/leap/bitmask/core/mail_services.py b/src/leap/bitmask/core/mail_services.py
index 6472bdc2..3495aa39 100644
--- a/src/leap/bitmask/core/mail_services.py
+++ b/src/leap/bitmask/core/mail_services.py
@@ -302,7 +302,7 @@ class KeymanagerContainer(Container):
class KeymanagerService(HookableService):
- def __init__(self, basedir='~/.config/leap'):
+ def __init__(self, basedir=DEFAULT_BASEDIR):
service.Service.__init__(self)
self._basedir = basedir
@@ -507,7 +507,7 @@ class SMTPService(service.Service):
name = 'smtp'
def __init__(self, soledad_sessions, keymanager_sessions, sendmail_opts,
- basedir='~/.config/leap'):
+ basedir=DEFAULT_BASEDIR):
self._basedir = os.path.expanduser(basedir)
port, factory = smtp.run_service(
diff --git a/src/leap/bitmask/core/service.py b/src/leap/bitmask/core/service.py
index ceda6353..ddd86155 100644
--- a/src/leap/bitmask/core/service.py
+++ b/src/leap/bitmask/core/service.py
@@ -33,7 +33,7 @@ from leap.common.events import server as event_server
class BitmaskBackend(configurable.ConfigurableService):
- def __init__(self, basedir='~/.config/leap'):
+ def __init__(self, basedir=configurable.DEFAULT_BASEDIR):
configurable.ConfigurableService.__init__(self, basedir)
--
cgit v1.2.3
From 08da5b11103cdd132c3ac4110ba42fcc8510a78b Mon Sep 17 00:00:00 2001
From: Kali Kaneko
Date: Sat, 30 Apr 2016 12:15:58 -0400
Subject: [refactor] pass backend to core service
---
src/leap/bitmask/core/flags.py | 1 +
src/leap/bitmask/core/launcher.py | 7 ++++++-
src/leap/bitmask/core/service.py | 13 ++++++++-----
3 files changed, 15 insertions(+), 6 deletions(-)
create mode 100644 src/leap/bitmask/core/flags.py
diff --git a/src/leap/bitmask/core/flags.py b/src/leap/bitmask/core/flags.py
new file mode 100644
index 00000000..9a40c70c
--- /dev/null
+++ b/src/leap/bitmask/core/flags.py
@@ -0,0 +1 @@
+BACKEND = 'default'
diff --git a/src/leap/bitmask/core/launcher.py b/src/leap/bitmask/core/launcher.py
index b2319077..b8916a1e 100644
--- a/src/leap/bitmask/core/launcher.py
+++ b/src/leap/bitmask/core/launcher.py
@@ -17,17 +17,22 @@
"""
Run bitmask daemon.
"""
-from twisted.scripts.twistd import run
from os.path import join
from sys import argv
+from twisted.scripts.twistd import run
+
from leap.bitmask.util import here
from leap.bitmask import core
+from leap.bitmask.core import flags
def run_bitmaskd():
# TODO --- configure where to put the logs... (get --logfile, --logdir
# from the bitmask_cli
+ for (index, arg) in enumerate(argv):
+ if arg == '--backend':
+ flags.BACKEND = argv[index + 1]
argv[1:] = [
'-y', join(here(core), "bitmaskd.tac"),
'--pidfile', '/tmp/bitmaskd.pid',
diff --git a/src/leap/bitmask/core/service.py b/src/leap/bitmask/core/service.py
index ddd86155..fca51048 100644
--- a/src/leap/bitmask/core/service.py
+++ b/src/leap/bitmask/core/service.py
@@ -17,6 +17,7 @@
"""
Bitmask-core Service.
"""
+import json
import resource
from twisted.internet import reactor
@@ -26,6 +27,7 @@ from leap.bitmask import __version__
from leap.bitmask.core import configurable
from leap.bitmask.core import mail_services
from leap.bitmask.core import _zmq
+from leap.bitmask.core import flags
from leap.bonafide.service import BonafideService
from leap.common.events import server as event_server
# from leap.vpn import EIPService
@@ -126,17 +128,18 @@ class BitmaskBackend(configurable.ConfigurableService):
# we may want to make this tuple a class member
services = ('soledad', 'keymanager', 'mail', 'eip')
- status_messages = []
+ status = {}
for name in services:
- status = 'stopped'
+ _status = 'stopped'
try:
if self.getServiceNamed(name).running:
- status = "running"
+ _status = 'running'
except KeyError:
pass
- status_messages.append("[{}: {}]".format(name, status))
+ status[name] = _status
+ status['backend'] = flags.BACKEND
- return " ".join(status_messages)
+ return json.dumps(status)
def do_version(self):
version = __version__
--
cgit v1.2.3
From 1173e77cb8d635936c9730ba4ad8b88b24ad1be2 Mon Sep 17 00:00:00 2001
From: Kali Kaneko
Date: Sun, 1 May 2016 11:09:07 -0400
Subject: [feature] pluggable backends and api registry
the idea behind this mechanism (partially implemented for that) is to be
able to check the backend output against some type annotations.
We want to be able to detect if a given backend (real services or
authoritative mocks) have diverged from what's specified in the API
annotations.
---
src/leap/bitmask/cli/bitmask_cli.py | 2 +-
src/leap/bitmask/core/api.py | 54 +++++++
src/leap/bitmask/core/api_contract.py | 40 +++++
src/leap/bitmask/core/dispatcher.py | 286 +++++++++++++++++++++------------
src/leap/bitmask/core/dummy.py | 80 +++++++++
src/leap/bitmask/core/mail_services.py | 10 +-
src/leap/bitmask/core/service.py | 86 ++++++----
7 files changed, 420 insertions(+), 138 deletions(-)
create mode 100644 src/leap/bitmask/core/api.py
create mode 100644 src/leap/bitmask/core/api_contract.py
create mode 100644 src/leap/bitmask/core/dummy.py
diff --git a/src/leap/bitmask/cli/bitmask_cli.py b/src/leap/bitmask/cli/bitmask_cli.py
index c5bb1b15..c2b1ba71 100755
--- a/src/leap/bitmask/cli/bitmask_cli.py
+++ b/src/leap/bitmask/cli/bitmask_cli.py
@@ -325,7 +325,7 @@ def send_command(cli):
s = get_zmq_connection()
- d = s.sendMsg(*data, timeout=20)
+ d = s.sendMsg(*data, timeout=60)
d.addCallback(cb)
d.addCallback(lambda x: reactor.stop())
d.addErrback(timeout_handler)
diff --git a/src/leap/bitmask/core/api.py b/src/leap/bitmask/core/api.py
new file mode 100644
index 00000000..9f3725dc
--- /dev/null
+++ b/src/leap/bitmask/core/api.py
@@ -0,0 +1,54 @@
+# -*- coding: utf-8 -*-
+# api.py
+# Copyright (C) 2016 LEAP Encryption Acess Project
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see .
+"""
+Registry for the public API for the Bitmask Backend.
+"""
+from collections import OrderedDict
+
+registry = OrderedDict()
+
+
+class APICommand(type):
+ """
+ A metaclass to keep a global registry of all the methods that compose the
+ public API for the Bitmask Backend.
+ """
+ def __init__(cls, name, bases, attrs):
+ for key, val in attrs.iteritems():
+ properties = getattr(val, 'register', None)
+ label = getattr(cls, 'label', None)
+ if label:
+ name = label
+ if properties is not None:
+ registry['%s.%s' % (name, key)] = properties
+
+
+def register_method(*args):
+ """
+ This method gathers info about all the methods that are supposed to
+ compose the public API to communicate with the backend.
+
+ It sets up a register property for any method that uses it.
+ A type annotation is supposed to be in this property.
+ The APICommand metaclass collects these properties of the methods and
+ stores them in the global api_registry object, where they can be
+ introspected at runtime.
+ """
+ def decorator(f):
+ f.register = tuple(args)
+ return f
+ return decorator
diff --git a/src/leap/bitmask/core/api_contract.py b/src/leap/bitmask/core/api_contract.py
new file mode 100644
index 00000000..86b600c1
--- /dev/null
+++ b/src/leap/bitmask/core/api_contract.py
@@ -0,0 +1,40 @@
+# -*- coding: utf-8 -*-
+# api_contract.py
+# Copyright (C) 2016 LEAP Encryption Acess Project
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see .
+"""
+Display a human-readable representation of the methods that compound the public
+api for Bitmask Core.
+
+The values are meant to be type annotations.
+"""
+
+if __name__ == "__main__":
+ from leap.bitmask.core.service import BitmaskBackend
+ from leap.bitmask.core import api
+ backend = BitmaskBackend()
+
+ print '========= Bitmask Core API =================='
+ print
+
+ for key in api.registry:
+ human_key = key.replace('do_', '').lower()
+ value = api.registry[key]
+
+ print("{}:\t\t{}".format(
+ human_key,
+ ' '.join([x for x in value])))
+ print
+ print '============================================='
diff --git a/src/leap/bitmask/core/dispatcher.py b/src/leap/bitmask/core/dispatcher.py
index 648cbe9b..e7c961fd 100644
--- a/src/leap/bitmask/core/dispatcher.py
+++ b/src/leap/bitmask/core/dispatcher.py
@@ -22,154 +22,214 @@ import json
from twisted.internet import defer
from twisted.python import failure, log
+from .api import APICommand, register_method
-# TODO implement sub-classes to dispatch subcommands (user, mail).
+class SubCommand(object):
-class CommandDispatcher(object):
+ __metaclass__ = APICommand
- def __init__(self, core):
+ def dispatch(self, service, *parts, **kw):
+ subcmd = parts[1]
- self.core = core
+ _method = getattr(self, 'do_' + subcmd.upper(), None)
+ if not _method:
+ raise RuntimeError('No such subcommand')
+ return _method(service, *parts, **kw)
- def _get_service(self, name):
- try:
- return self.core.getServiceNamed(name)
- except KeyError:
- return None
+class UserCmd(SubCommand):
- def dispatch(self, msg):
- cmd = msg[0]
+ label = 'user'
- _method = getattr(self, 'do_' + cmd.upper(), None)
+ @register_method("{'srp_token': unicode, 'uuid': unicode}")
+ def do_AUTHENTICATE(self, bonafide, *parts):
+ user, password = parts[2], parts[3]
+ d = defer.maybeDeferred(bonafide.do_authenticate, user, password)
+ return d
- if not _method:
- return defer.fail(failure.Failure(RuntimeError('No such command')))
+ @register_method("{'signup': 'ok', 'user': str}")
+ def do_SIGNUP(self, bonafide, *parts):
+ user, password = parts[2], parts[3]
+ d = defer.maybeDeferred(bonafide.do_signup, user, password)
+ return d
- return defer.maybeDeferred(_method, *msg)
+ @register_method("{'logout': 'ok'}")
+ def do_LOGOUT(self, bonafide, *parts):
+ user, password = parts[2], parts[3]
+ d = defer.maybeDeferred(bonafide.do_logout, user, password)
+ return d
- def do_STATS(self, *parts):
- return _format_result(self.core.do_stats())
+ @register_method('str')
+ def do_ACTIVE(self, bonafide, *parts):
+ d = defer.maybeDeferred(bonafide.do_get_active_user)
+ return d
- def do_VERSION(self, *parts):
- return _format_result(self.core.do_version())
- def do_STATUS(self, *parts):
- return _format_result(self.core.do_status())
+class EIPCmd(SubCommand):
- def do_SHUTDOWN(self, *parts):
- return _format_result(self.core.do_shutdown())
+ label = 'eip'
- def do_USER(self, *parts):
+ @register_method('dict')
+ def do_ENABLE(self, service, *parts):
+ d = service.do_enable_service(self.label)
+ return d
- subcmd = parts[1]
- user, password = parts[2], parts[3]
+ @register_method('dict')
+ def do_DISABLE(self, service, *parts):
+ d = service.do_disable_service(self.label)
+ return d
- bf = self._get_service('bonafide')
+ @register_method('dict')
+ def do_STATUS(self, eip, *parts):
+ d = eip.do_status()
+ return d
- if subcmd == 'authenticate':
- d = bf.do_authenticate(user, password)
+ @register_method('dict')
+ def do_START(self, eip, *parts):
+ # TODO --- attempt to get active provider
+ # TODO or catch the exception and send error
+ provider = parts[2]
+ d = eip.do_start(provider)
+ return d
- elif subcmd == 'signup':
- d = bf.do_signup(user, password)
+ @register_method('dict')
+ def do_STOP(self, eip, *parts):
+ d = eip.do_stop()
+ return d
- elif subcmd == 'logout':
- d = bf.do_logout(user, password)
- elif subcmd == 'active':
- d = bf.do_get_active_user()
+class MailCmd(SubCommand):
- d.addCallbacks(_format_result, _format_error)
+ label = 'mail'
+
+ @register_method('dict')
+ def do_ENABLE(self, service, *parts):
+ d = service.do_enable_service(self.label)
return d
- def do_EIP(self, *parts):
+ @register_method('dict')
+ def do_DISABLE(self, service, *parts):
+ d = service.do_disable_service(self.label)
+ return d
- subcmd = parts[1]
- eip_label = 'eip'
+ @register_method('dict')
+ def do_STATUS(self, mail, *parts):
+ d = mail.do_status()
+ return d
- if subcmd == 'enable':
- return _format_result(
- self.core.do_enable_service(eip_label))
+ @register_method('dict')
+ def do_GET_IMAP_TOKEN(self, mail, *parts):
+ d = mail.get_imap_token()
+ return d
- eip = self._get_service(eip_label)
- if not eip:
- return _format_result('eip: disabled')
+ @register_method('dict')
+ def do_GET_SMTP_TOKEN(self, mail, *parts):
+ d = mail.get_smtp_token()
+ return d
- if subcmd == 'status':
- return _format_result(eip.do_status())
+ @register_method('dict')
+ def do_GET_SMTP_CERTIFICATE(self, mail, *parts, **kw):
+ # TODO move to mail service
+ # TODO should ask for confirmation? like --force or something,
+ # if we already have a valid one. or better just refuse if cert
+ # exists.
+ # TODO how should we pass the userid??
+ # - Keep an 'active' user in bonafide (last authenticated)
+ # (doing it now)
+ # - Get active user from Mail Service (maybe preferred?)
+ # - Have a command/method to set 'active' user.
+
+ @defer.inlineCallbacks
+ def save_cert(cert_data):
+ userid, cert_str = cert_data
+ cert_path = yield mail.do_get_smtp_cert_path(userid)
+ with open(cert_path, 'w') as outf:
+ outf.write(cert_str)
+ defer.returnValue('certificate saved to %s' % cert_path)
+
+ bonafide = kw['bonafide']
+ d = bonafide.do_get_smtp_cert()
+ d.addCallback(save_cert)
+ return d
- elif subcmd == 'disable':
- return _format_result(
- self.core.do_disable_service(eip_label))
- elif subcmd == 'start':
- # TODO --- attempt to get active provider
- # TODO or catch the exception and send error
- provider = parts[2]
- d = eip.do_start(provider)
- d.addCallbacks(_format_result, _format_error)
- return d
+class CommandDispatcher(object):
- elif subcmd == 'stop':
- d = eip.do_stop()
- d.addCallbacks(_format_result, _format_error)
- return d
+ __metaclass__ = APICommand
- def do_MAIL(self, *parts):
+ label = 'core'
+ def __init__(self, core):
+
+ self.core = core
+ self.subcommand_user = UserCmd()
+ self.subcommand_eip = EIPCmd()
+ self.subcommand_mail = MailCmd()
+
+ # XXX --------------------------------------------
+ # TODO move general services to another subclass
+
+ @register_method("{'mem_usage': str}")
+ def do_STATS(self, *parts):
+ return _format_result(self.core.do_stats())
+
+ @register_method("{version_core': '0.0.0'}")
+ def do_VERSION(self, *parts):
+ return _format_result(self.core.do_version())
+
+ @register_method("{'mail': 'running'}")
+ def do_STATUS(self, *parts):
+ return _format_result(self.core.do_status())
+
+ @register_method("{'shutdown': 'ok'}")
+ def do_SHUTDOWN(self, *parts):
+ return _format_result(self.core.do_shutdown())
+
+ # -----------------------------------------------
+
+ def do_USER(self, *parts):
+ bonafide = self._get_service('bonafide')
+ d = self.subcommand_user.dispatch(bonafide, *parts)
+ d.addCallbacks(_format_result, _format_error)
+ return d
+
+ def do_EIP(self, *parts):
+ eip = self._get_service(self.subcommand_eip.label)
+ if not eip:
+ return _format_result('eip: disabled')
subcmd = parts[1]
- mail_label = 'mail'
- if subcmd == 'enable':
- return _format_result(
- self.core.do_enable_service(mail_label))
+ dispatch = self._subcommand_eip.dispatch
+ if subcmd in ('enable', 'disable'):
+ d = dispatch(self.core, *parts)
+ else:
+ d = dispatch(eip, *parts)
- m = self._get_service(mail_label)
- bf = self._get_service('bonafide')
+ d.addCallbacks(_format_result, _format_error)
+ return d
- if not m:
- return _format_result('mail: disabled')
+ def do_MAIL(self, *parts):
+ subcmd = parts[1]
+ dispatch = self.subcommand_mail.dispatch
- if subcmd == 'status':
- return _format_result(m.do_status())
+ if subcmd == 'enable':
+ d = dispatch(self.core, *parts)
- elif subcmd == 'disable':
- return _format_result(self.core.do_disable_service(mail_label))
+ mail = self._get_service(self.subcommand_mail.label)
+ bonafide = self._get_service('bonafide')
+ kw = {'bonafide': bonafide}
- elif subcmd == 'get_imap_token':
- d = m.get_imap_token()
- d.addCallbacks(_format_result, _format_error)
- return d
+ if not mail:
+ return _format_result('mail: disabled')
- elif subcmd == 'get_smtp_token':
- d = m.get_smtp_token()
- d.addCallbacks(_format_result, _format_error)
- return d
+ if subcmd == 'disable':
+ d = dispatch(self.core)
+ else:
+ d = dispatch(mail, *parts, **kw)
- elif subcmd == 'get_smtp_certificate':
- # TODO move to mail service
- # TODO should ask for confirmation? like --force or something,
- # if we already have a valid one. or better just refuse if cert
- # exists.
- # TODO how should we pass the userid??
- # - Keep an 'active' user in bonafide (last authenticated)
- # (doing it now)
- # - Get active user from Mail Service (maybe preferred?)
- # - Have a command/method to set 'active' user.
-
- @defer.inlineCallbacks
- def save_cert(cert_data):
- userid, cert_str = cert_data
- cert_path = yield m.do_get_smtp_cert_path(userid)
- with open(cert_path, 'w') as outf:
- outf.write(cert_str)
- defer.returnValue('certificate saved to %s' % cert_path)
-
- d = bf.do_get_smtp_cert()
- d.addCallback(save_cert)
- d.addCallbacks(_format_result, _format_error)
- return d
+ d.addCallbacks(_format_result, _format_error)
+ return d
def do_KEYS(self, *parts):
subcmd = parts[1]
@@ -187,6 +247,22 @@ class CommandDispatcher(object):
d.addCallbacks(_format_result, _format_error)
return d
+ def dispatch(self, msg):
+ cmd = msg[0]
+
+ _method = getattr(self, 'do_' + cmd.upper(), None)
+
+ if not _method:
+ return defer.fail(failure.Failure(RuntimeError('No such command')))
+
+ return defer.maybeDeferred(_method, *msg)
+
+ def _get_service(self, name):
+ try:
+ return self.core.getServiceNamed(name)
+ except KeyError:
+ return None
+
def _format_result(result):
return json.dumps({'error': None, 'result': result})
diff --git a/src/leap/bitmask/core/dummy.py b/src/leap/bitmask/core/dummy.py
new file mode 100644
index 00000000..99dfafa5
--- /dev/null
+++ b/src/leap/bitmask/core/dummy.py
@@ -0,0 +1,80 @@
+# -*- coding: utf-8 -*-
+# dummy.py
+# Copyright (C) 2016 LEAP Encryption Acess Project
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see .
+"""
+An authoritative dummy backend for tests.
+"""
+import json
+
+from leap.common.service_hooks import HookableService
+
+
+class BackendCommands(object):
+
+ """
+ General commands for the BitmaskBackend Core Service.
+ """
+
+ def __init__(self, core):
+ self.core = core
+
+ def do_status(self):
+ return json.dumps(
+ {'soledad': 'running',
+ 'keymanager': 'running',
+ 'mail': 'running',
+ 'eip': 'stopped',
+ 'backend': 'dummy'})
+
+ def do_version(self):
+ return {'version_core': '0.0.1'}
+
+ def do_stats(self):
+ return {'mem_usage': '01 KB'}
+
+ def do_shutdown(self):
+ return {'shutdown': 'ok'}
+
+
+class mail_services(object):
+
+ class SoledadService(HookableService):
+ pass
+
+ class KeymanagerService(HookableService):
+ pass
+
+ class StandardMailService(HookableService):
+ pass
+
+
+class BonafideService(HookableService):
+
+ def __init__(self, basedir):
+ pass
+
+ def do_authenticate(self, user, password):
+ return {u'srp_token': u'deadbeef123456789012345678901234567890123',
+ u'uuid': u'01234567890abcde01234567890abcde'}
+
+ def do_signup(self, user, password):
+ return {'signup': 'ok', 'user': 'dummyuser@provider.example.org'}
+
+ def do_logout(self, user, password):
+ return {'logout': 'ok'}
+
+ def do_get_active_user(self):
+ return 'dummyuser@provider.example.org'
diff --git a/src/leap/bitmask/core/mail_services.py b/src/leap/bitmask/core/mail_services.py
index 3495aa39..fb9ee698 100644
--- a/src/leap/bitmask/core/mail_services.py
+++ b/src/leap/bitmask/core/mail_services.py
@@ -64,10 +64,10 @@ class ImproperlyConfigured(Exception):
class SoledadContainer(Container):
- def __init__(self, basedir=DEFAULT_BASEDIR):
+ def __init__(self, service=None, basedir=DEFAULT_BASEDIR):
self._basedir = os.path.expanduser(basedir)
self._usermap = UserMap()
- super(SoledadContainer, self).__init__()
+ super(SoledadContainer, self).__init__(service=service)
def add_instance(self, userid, passphrase, uuid=None, token=None):
@@ -89,7 +89,7 @@ class SoledadContainer(Container):
uuid, passphrase, soledad_path, soledad_url,
cert_path, token)
- self.add_instances(userid, soledad)
+ super(SoledadContainer, self).add_instance(userid, soledad)
data = {'user': userid, 'uuid': uuid, 'token': token,
'soledad': soledad}
@@ -202,9 +202,9 @@ class SoledadService(HookableService):
class KeymanagerContainer(Container):
- def __init__(self, basedir):
+ def __init__(self, service=None, basedir=DEFAULT_BASEDIR):
self._basedir = os.path.expanduser(basedir)
- super(KeymanagerContainer, self).__init__()
+ super(KeymanagerContainer, self).__init__(service=service)
def add_instance(self, userid, token, uuid, soledad):
diff --git a/src/leap/bitmask/core/service.py b/src/leap/bitmask/core/service.py
index fca51048..99132c2d 100644
--- a/src/leap/bitmask/core/service.py
+++ b/src/leap/bitmask/core/service.py
@@ -25,19 +25,30 @@ from twisted.python import log
from leap.bitmask import __version__
from leap.bitmask.core import configurable
-from leap.bitmask.core import mail_services
from leap.bitmask.core import _zmq
from leap.bitmask.core import flags
-from leap.bonafide.service import BonafideService
from leap.common.events import server as event_server
# from leap.vpn import EIPService
+backend = flags.BACKEND
+
+if backend == 'default':
+ from leap.bitmask.core import mail_services
+ from leap.bonafide.service import BonafideService
+elif backend == 'dummy':
+ from leap.bitmask.core.dummy import mail_services
+ from leap.bitmask.core.dummy import BonafideService
+else:
+ raise RuntimeError('Backend not supported')
+
+
class BitmaskBackend(configurable.ConfigurableService):
def __init__(self, basedir=configurable.DEFAULT_BASEDIR):
configurable.ConfigurableService.__init__(self, basedir)
+ self.core_commands = BackendCommands(self)
def enabled(service):
return self.get_config('services', service, False, boolean=True)
@@ -117,38 +128,19 @@ class BitmaskBackend(configurable.ConfigurableService):
service.setServiceParent(self)
return service
- # General commands for the BitmaskBackend Core Service
-
def do_stats(self):
- log.msg('BitmaskCore Service STATS')
- mem = resource.getrusage(resource.RUSAGE_SELF).ru_maxrss
- return 'BitmaskCore: [Mem usage: %s KB]' % (mem / 1024)
+ return self.core_commands.do_stats()
def do_status(self):
- # we may want to make this tuple a class member
- services = ('soledad', 'keymanager', 'mail', 'eip')
-
- status = {}
- for name in services:
- _status = 'stopped'
- try:
- if self.getServiceNamed(name).running:
- _status = 'running'
- except KeyError:
- pass
- status[name] = _status
- status['backend'] = flags.BACKEND
-
- return json.dumps(status)
+ return self.core_commands.do_status()
def do_version(self):
- version = __version__
- return 'BitmaskCore: %s' % version
+ return self.core_commands.do_version()
def do_shutdown(self):
- self.stopService()
- reactor.callLater(1, reactor.stop)
- return 'shutting down...'
+ return self.core_commands.do_shutdown()
+
+ # Service Toggling
def do_enable_service(self, service):
assert service in self.service_names
@@ -175,3 +167,43 @@ class BitmaskBackend(configurable.ConfigurableService):
# TODO -- should stop also?
self.set_config('services', service, 'False')
return 'ok'
+
+
+class BackendCommands(object):
+
+ """
+ General commands for the BitmaskBackend Core Service.
+ """
+
+ def __init__(self, core):
+ self.core = core
+
+ def do_status(self):
+ # we may want to make this tuple a class member
+ services = ('soledad', 'keymanager', 'mail', 'eip')
+
+ status = {}
+ for name in services:
+ _status = 'stopped'
+ try:
+ if self.core.getServiceNamed(name).running:
+ _status = 'running'
+ except KeyError:
+ pass
+ status[name] = _status
+ status['backend'] = flags.BACKEND
+
+ return json.dumps(status)
+
+ def do_version(self):
+ return {'version_core': __version__}
+
+ def do_stats(self):
+ log.msg('BitmaskCore Service STATS')
+ mem = resource.getrusage(resource.RUSAGE_SELF).ru_maxrss
+ return {'mem_usage': '%s KB' % (mem / 1024)}
+
+ def do_shutdown(self):
+ self.core.stopService()
+ reactor.callLater(1, reactor.stop)
+ return {'shutdown': 'ok'}
--
cgit v1.2.3
From cfdd93937a7af65be73d5cc482686d1fe559d0a9 Mon Sep 17 00:00:00 2001
From: Kali Kaneko
Date: Tue, 3 May 2016 10:18:06 -0400
Subject: [refactor] rename and move api_contract
---
docs/core_api_contract | 41 +++++++++++++++++++++++++++++++++++
src/leap/bitmask/core/api_contract.py | 40 ----------------------------------
2 files changed, 41 insertions(+), 40 deletions(-)
create mode 100755 docs/core_api_contract
delete mode 100644 src/leap/bitmask/core/api_contract.py
diff --git a/docs/core_api_contract b/docs/core_api_contract
new file mode 100755
index 00000000..b70fb8fa
--- /dev/null
+++ b/docs/core_api_contract
@@ -0,0 +1,41 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+# api_contract.py
+# Copyright (C) 2016 LEAP Encryption Acess Project
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see .
+"""
+Display a human-readable representation of the methods that compound the public
+api for Bitmask Core.
+
+The values are meant to be type annotations.
+"""
+
+if __name__ == "__main__":
+ from leap.bitmask.core.service import BitmaskBackend
+ from leap.bitmask.core import api
+ backend = BitmaskBackend()
+
+ print '========= Bitmask Core API =================='
+ print
+
+ for key in api.registry:
+ human_key = key.replace('do_', '').lower()
+ value = api.registry[key]
+
+ print("{}:\t\t{}".format(
+ human_key,
+ ' '.join([x for x in value])))
+ print
+ print '============================================='
diff --git a/src/leap/bitmask/core/api_contract.py b/src/leap/bitmask/core/api_contract.py
deleted file mode 100644
index 86b600c1..00000000
--- a/src/leap/bitmask/core/api_contract.py
+++ /dev/null
@@ -1,40 +0,0 @@
-# -*- coding: utf-8 -*-
-# api_contract.py
-# Copyright (C) 2016 LEAP Encryption Acess Project
-#
-# This program is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program. If not, see .
-"""
-Display a human-readable representation of the methods that compound the public
-api for Bitmask Core.
-
-The values are meant to be type annotations.
-"""
-
-if __name__ == "__main__":
- from leap.bitmask.core.service import BitmaskBackend
- from leap.bitmask.core import api
- backend = BitmaskBackend()
-
- print '========= Bitmask Core API =================='
- print
-
- for key in api.registry:
- human_key = key.replace('do_', '').lower()
- value = api.registry[key]
-
- print("{}:\t\t{}".format(
- human_key,
- ' '.join([x for x in value])))
- print
- print '============================================='
--
cgit v1.2.3
From 2a802378a6ffd1c1c677e4fa035ee3b8f932dfbe Mon Sep 17 00:00:00 2001
From: Kali Kaneko
Date: Tue, 3 May 2016 10:40:30 -0400
Subject: [pkg] remove pixelated readme, can be enabled in prefswin
---
pkg/PixelatedWebmail.README | 38 --------------------------------------
pkg/pyinst/pyinst-build.mk | 1 -
2 files changed, 39 deletions(-)
delete mode 100644 pkg/PixelatedWebmail.README
diff --git a/pkg/PixelatedWebmail.README b/pkg/PixelatedWebmail.README
deleted file mode 100644
index 06e52964..00000000
--- a/pkg/PixelatedWebmail.README
+++ /dev/null
@@ -1,38 +0,0 @@
-How to enable Pixelated Webmail
--------------------------------
-
-WARNING! This is an experimental feature.
-It can expose your mail to *any* user with access to your machine, since there
-is no authentication in place at the moment. It could even eat your data. You
-have been warned.
-
-Ok, how do I enable this wonderful feature?
--------------------------------------------
-
-First, run the bundle for a first time, and ensure that you can register a new
-account with a mail-enabled provider (for instance, mail.bitmask.net).
-
-Then, you have to edit a config file living inside the bundle folders. You have
-to add "Pixmail=true" under the [General] section, like this:
-
-lib/config/leap/leap.conf:
-
-[General]
-SkipFirstRun=true
-Provider=mail.bitmask.net
-Pixmail=true
-
-[mail.bitmask.net]
-Services=mx
-
-Then, run bitmask again:
-
-./bitmask --debug
-
-And a new "Bitmask Webmail" option should have appeared under the "Bitmask"
-menu.
-
-If you want to disable the Webmail functionality, just set the Pixmail property
-to 'false'.
-
-Enjoy your local and encrypted pixelated webmail!
diff --git a/pkg/pyinst/pyinst-build.mk b/pkg/pyinst/pyinst-build.mk
index 664f13ec..32239f8e 100644
--- a/pkg/pyinst/pyinst-build.mk
+++ b/pkg/pyinst/pyinst-build.mk
@@ -55,7 +55,6 @@ pyinst-cleanup:
pyinst-distribution-data:
cp release-notes.rst $(DIST_VERSION)
- cp pkg/PixelatedWebmail.README $(DIST_VERSION)
cp LICENSE $(DIST_VERSION)
pyinst-helpers-linux:
--
cgit v1.2.3
From 54560623ac5c325bebbe627582b3895c3354368a Mon Sep 17 00:00:00 2001
From: Kali Kaneko
Date: Tue, 3 May 2016 12:18:25 -0400
Subject: [feature] enable to download attachments from within webkit
- Resolves: #8069
- Releases: 0.9.2
---
src/leap/bitmask/gui/qt_browser.py | 30 +++++++++++++++++++++++++++++-
1 file changed, 29 insertions(+), 1 deletion(-)
diff --git a/src/leap/bitmask/gui/qt_browser.py b/src/leap/bitmask/gui/qt_browser.py
index c62e7770..2f7e6086 100644
--- a/src/leap/bitmask/gui/qt_browser.py
+++ b/src/leap/bitmask/gui/qt_browser.py
@@ -17,8 +17,10 @@
"""
QtWebKit-based browser to display Pixelated User Agent
"""
+import os
+import urlparse
-from PySide import QtCore, QtWebKit, QtGui
+from PySide import QtCore, QtWebKit, QtGui, QtNetwork
PIXELATED_URI = 'http://localhost:9090'
@@ -37,3 +39,29 @@ class PixelatedWindow(QtGui.QDialog):
def load_app(self):
self.view.load(QtCore.QUrl(PIXELATED_URI))
+ self.view.page().setForwardUnsupportedContent(True)
+ self.view.page().unsupportedContent.connect(self.download)
+
+ self.manager = QtNetwork.QNetworkAccessManager()
+ self.manager.finished.connect(self.finished)
+
+ def download(self, reply):
+ self.request = QtNetwork.QNetworkRequest(reply.url())
+ self.reply = self.manager.get(self.request)
+
+ def finished(self):
+ url = self.reply.url().toString()
+
+ filename = urlparse.parse_qs(url).get('filename', None)
+ if filename:
+ filename = filename[0]
+ name = filename or url
+
+ path = os.path.expanduser(os.path.join(
+ '~', unicode(name).split('/')[-1]))
+ destination = QtGui.QFileDialog.getSaveFileName(self, "Save", path)
+ if destination:
+ filename = destination[0]
+ with open(filename, 'wb') as f:
+ f.write(str(self.reply.readAll()))
+ f.close()
--
cgit v1.2.3
From e7439f48b4279dcda0dc966903840a2affee3353 Mon Sep 17 00:00:00 2001
From: elijah
Date: Wed, 11 May 2016 14:45:09 -0700
Subject: [bug] add scrollbars to mail preference panel
---
src/leap/bitmask/gui/preferences_email_page.py | 20 +-
src/leap/bitmask/gui/ui/preferences_email_page.ui | 648 ++++++++++++----------
2 files changed, 354 insertions(+), 314 deletions(-)
diff --git a/src/leap/bitmask/gui/preferences_email_page.py b/src/leap/bitmask/gui/preferences_email_page.py
index 7186450d..0f44dfee 100644
--- a/src/leap/bitmask/gui/preferences_email_page.py
+++ b/src/leap/bitmask/gui/preferences_email_page.py
@@ -65,20 +65,16 @@ class PreferencesEmailPage(PreferencesPage):
"Search for \"Bitmask\" in the add-on manager or "
"download it from addons.mozilla.org.".format(
thunderbird_extension_url)))
+
self.ui.mail_client_label.setText(self.tr(
"Alternatively, you can manually configure your mail client to "
- "use Bitmask Email with these options:"))
+ "use Bitmask with these options:"))
self.ui.webmail_label.setText(self.tr(
- "This distribution of Bitmask ships an experimental integration "
- "of Pixelated "
- "Mail. Note: at the current state, anyone with access to "
- "your device can read your mail without authentication, "
- "by opening a browser pointing to http://localhost:9090 "))
- webmail_enabled = self.settings.get_pixelmail_enabled()
- self.ui.webmail_checkbox.setChecked(webmail_enabled)
- if not HAS_PIXELATED:
- self.ui.webmail_box.setVisible(False)
+ "Bitmask Mail is an integrated mail client based "
+ "on Pixelated "
+ "User Agent. If enabled, any user on your device "
+ "can read your mail by opening http://localhost:9090"))
self.ui.keys_table.horizontalHeader().setResizeMode(
0, QtGui.QHeaderView.Stretch)
@@ -122,6 +118,10 @@ class PreferencesEmailPage(PreferencesPage):
self.ui.message_label.setText(
self.tr('You must be logged in to edit email settings.'))
else:
+ webmail_enabled = self.settings.get_pixelmail_enabled()
+ self.ui.webmail_checkbox.setChecked(webmail_enabled)
+ if not HAS_PIXELATED:
+ self.ui.webmail_box.setVisible(False)
self.ui.import_button.setVisible(False) # hide this until working
self.ui.message_label.setVisible(False)
self.ui.email_tabs.setVisible(True)
diff --git a/src/leap/bitmask/gui/ui/preferences_email_page.ui b/src/leap/bitmask/gui/ui/preferences_email_page.ui
index e4a72951..610a43c7 100644
--- a/src/leap/bitmask/gui/ui/preferences_email_page.ui
+++ b/src/leap/bitmask/gui/ui/preferences_email_page.ui
@@ -32,345 +32,385 @@
+
+ background: palette(base);
+ Tab 1
-
-
- Bitmask Mail
+
+
+
-
-
-
-
- Enable Bitmask Mail (needs restart)
-
-
-
-
-
-
- webmail info
-
-
- true
-
-
-
-
-
-
-
-
-
- Thunderbird Configuration
+
+ QFrame::NoFrame
-
-
-
-
- thunderbird information
-
-
- true
-
-
-
-
-
-
-
-
-
-
- 0
- 0
-
-
-
- Other Mail Clients Configuration
+
+ true
-
-
-
-
- mail client information
-
-
- true
-
-
-
-
-
-
-
-
-
-
-
- 0
- 0
-
-
-
- Host
-
-
- Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
-
-
-
-
-
-
-
- 0
- 0
-
-
+
+
+
+ 0
+ 0
+ 504
+ 537
+
+
+
+ false
+
+
+ background: palette(base);
+
+
+
+ 6
+
+
+ 0
+
+
+
+
+ Bitmask Mail
+
+
+
+
- Port
-
-
- Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
+ Enable Bitmask Mail (needs restart)
-
-
-
-
- 0
- 0
-
-
-
-
- 100
- 16777215
-
-
+
+
-
+ webmail info
-
+ true
-
-
-
-
- 0
- 0
-
-
+
+
+
+
+
+
+ Thunderbird Configuration
+
+
+
+
- TLS: off
-
-
-
-
-
-
-
- 0
- 0
-
-
-
-
- 50
- 16777215
-
+ thunderbird information
-
+ true
-
-
-
- Qt::Horizontal
-
-
-
- 40
- 20
-
-
-
-
-
-
-
-
- IMAP
-
-
-
-
-
-
- Username
-
-
-
-
-
-
- SMTP
-
-
-
-
-
-
-
-
-
- 0
- 0
-
-
+
+
+
+
+
+
+ 0
+ 0
+
+
+
+ Other Mail Clients Configuration
+
+
+
+
- Host
+ mail client information
-
- Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
-
-
-
-
-
-
-
- 0
- 0
-
-
-
-
- 100
- 16777215
-
-
-
-
-
-
+ true
-
-
-
-
- 0
- 0
-
-
-
- Port
-
-
- Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
-
-
-
-
-
-
- Qt::Horizontal
-
-
-
- 40
- 20
-
-
-
-
-
-
-
-
- 0
- 0
-
-
-
- TLS: off
-
-
-
-
-
-
-
- 0
- 0
-
-
-
-
- 50
- 16777215
-
-
-
- true
-
-
+
+
+
+
+
+
+
+
+ 0
+ 0
+
+
+
+ Host
+
+
+ Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
+
+
+
+
+
+
+
+ 0
+ 0
+
+
+
+ Port
+
+
+ Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
+
+
+
+
+
+
+
+ 0
+ 0
+
+
+
+
+ 100
+ 16777215
+
+
+
+
+
+
+ true
+
+
+
+
+
+
+
+ 0
+ 0
+
+
+
+ TLS: off
+
+
+
+
+
+
+
+ 0
+ 0
+
+
+
+
+ 50
+ 16777215
+
+
+
+ true
+
+
+
+
+
+
+ Qt::Horizontal
+
+
+
+ 40
+ 20
+
+
+
+
+
+
+
+
+
+ IMAP
+
+
+
+
+
+
+ Username
+
+
+
+
+
+
+ SMTP
+
+
+
+
+
+
+
+
+
+ 0
+ 0
+
+
+
+ Host
+
+
+ Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
+
+
+
+
+
+
+
+ 0
+ 0
+
+
+
+
+ 100
+ 16777215
+
+
+
+
+
+
+ true
+
+
+
+
+
+
+
+ 0
+ 0
+
+
+
+ Port
+
+
+ Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
+
+
+
+
+
+
+ Qt::Horizontal
+
+
+
+ 40
+ 20
+
+
+
+
+
+
+
+
+ 0
+ 0
+
+
+
+ TLS: off
+
+
+
+
+
+
+
+ 0
+ 0
+
+
+
+
+ 50
+ 16777215
+
+
+
+ true
+
+
+
+
+
+
+
+
+ true
+
+
+
+
+
+
+ Password
+
+
+
+
+
+
+ true
+
+
+
+
-
-
-
-
- true
-
-
-
-
-
-
- Password
-
-
-
-
-
-
- true
-
-
-
-
-
-
+
+
+
+
+
+ Qt::Vertical
+
+
+
+ 20
+ 4
+
+
+
+
+
+
-
-
-
- Qt::Vertical
-
-
-
- 20
- 40
-
-
-
-
--
cgit v1.2.3
From c7f9bbcc8fe075750e4041c5a7f00c8767dd38b5 Mon Sep 17 00:00:00 2001
From: elijah
Date: Wed, 11 May 2016 15:03:23 -0700
Subject: [feat] Make help menu item open bitmask.net/help directly
---
src/leap/bitmask/gui/mainwindow.py | 50 +++-----------------------------------
1 file changed, 3 insertions(+), 47 deletions(-)
diff --git a/src/leap/bitmask/gui/mainwindow.py b/src/leap/bitmask/gui/mainwindow.py
index daf49eb6..25ee4f3d 100644
--- a/src/leap/bitmask/gui/mainwindow.py
+++ b/src/leap/bitmask/gui/mainwindow.py
@@ -1054,53 +1054,9 @@ class MainWindow(QtGui.QMainWindow, SignalTracker):
TRIGGERS:
self.ui.action_help.triggered
- Display the Bitmask help dialog.
- """
- # TODO: don't hardcode!
- smtp_port = 2013
-
- help_url = "
".format(
- self.tr("bitmask.net/help"))
-
- lang = QtCore.QLocale.system().name().replace('_', '-')
- thunderbird_extension_url = \
- "https://addons.mozilla.org/{0}/" \
- "thunderbird/addon/bitmask/".format(lang)
-
- email_quick_reference = self.tr("Email quick reference")
- thunderbird_text = self.tr(
- "For Thunderbird, you can use the "
- "Bitmask extension. Search for \"Bitmask\" in the add-on "
- "manager or download it from "
- "addons.mozilla.org.".format(thunderbird_extension_url))
- manual_text = self.tr(
- "Alternatively, you can manually configure "
- "your mail client to use Bitmask Email with these options:")
- manual_imap = self.tr("IMAP: localhost, port {0}".format(IMAP_PORT))
- manual_smtp = self.tr("SMTP: localhost, port {0}".format(smtp_port))
- manual_username = self.tr("Username: your full email address")
-
- # FIXME on i3, this doens't allow to mouse-select.
- # Switch to a dialog in which we can set the QLabel
- mail_auth_token = (
- self.app.service_tokens.get('mail_auth', None) or
- "??? (log in to unlock)")
- mail_password = self.tr("IMAP/SMTP Password:") + " %s" % (
- mail_auth_token,)
-
- msg = help_url + self.tr(
- "
{0}
"
- "
{1}
"
- "
{2}"
- "
"
- "
{3}
"
- "
{4}
"
- "
{5}
"
- "
{6}
"
- "
").format(email_quick_reference, thunderbird_text,
- manual_text, manual_imap, manual_smtp,
- manual_username, mail_password)
- QtGui.QMessageBox.about(self, self.tr("Bitmask Help"), msg)
+ Open bitmask.net/help
+ """
+ QtGui.QDesktopServices.openUrl("https://bitmask.net/help")
def _needs_update(self):
"""
--
cgit v1.2.3
From cd95c8d2e285538e282dbf2b5e848b4154c3606c Mon Sep 17 00:00:00 2001
From: elijah
Date: Wed, 11 May 2016 15:05:57 -0700
Subject: [bug] remove "about bitmask" easter egg
---
src/leap/bitmask/gui/mainwindow.py | 5 +----
1 file changed, 1 insertion(+), 4 deletions(-)
diff --git a/src/leap/bitmask/gui/mainwindow.py b/src/leap/bitmask/gui/mainwindow.py
index 25ee4f3d..e7b849e5 100644
--- a/src/leap/bitmask/gui/mainwindow.py
+++ b/src/leap/bitmask/gui/mainwindow.py
@@ -1030,12 +1030,9 @@ class MainWindow(QtGui.QMainWindow, SignalTracker):
Display the About Bitmask dialog
"""
today = datetime.now().date()
- greet = ("Happy New 1984!... or not ;)
"
- if today.month == 1 and today.day < 15 else "")
title = self.tr("About Bitmask - %s") % (VERSION,)
msg = self.tr(
"Version: {ver} ({ver_hash}) "
- " {greet}"
"Bitmask is the Desktop client application for the LEAP "
"platform, supporting Encrypted Internet Proxy "
"and "
@@ -1046,7 +1043,7 @@ class MainWindow(QtGui.QMainWindow, SignalTracker):
"available. "
" "
"More about LEAP")
- msg = msg.format(ver=VERSION, ver_hash=VERSION_HASH[:10], greet=greet)
+ msg = msg.format(ver=VERSION, ver_hash=VERSION_HASH[:10])
QtGui.QMessageBox.about(self, title, msg)
def _help(self):
--
cgit v1.2.3
From 61970d6395afcaa5439d866fbfb1ab2ad471141a Mon Sep 17 00:00:00 2001
From: elijah
Date: Wed, 11 May 2016 17:09:54 -0700
Subject: [feat] move pix UA launcher from menu to mail status widget.
---
src/leap/bitmask/gui/mail_status.py | 52 +++++--
src/leap/bitmask/gui/mainwindow.py | 12 --
src/leap/bitmask/gui/preferenceswindow.py | 15 ++
src/leap/bitmask/gui/ui/mail_status.ui | 239 +++++++++++++++++-------------
src/leap/bitmask/gui/ui/mainwindow.ui | 10 +-
src/leap/bitmask/gui/ui/preferences.ui | 2 +-
6 files changed, 197 insertions(+), 133 deletions(-)
diff --git a/src/leap/bitmask/gui/mail_status.py b/src/leap/bitmask/gui/mail_status.py
index 419a85c0..1045343b 100644
--- a/src/leap/bitmask/gui/mail_status.py
+++ b/src/leap/bitmask/gui/mail_status.py
@@ -26,7 +26,9 @@ from leap.common.check import leap_assert, leap_assert_type
from leap.common.events import register
from leap.common.events import catalog
+from leap.bitmask.gui.preferenceswindow import PreferencesWindow
from ui_mail_status import Ui_MailStatusWidget
+from .qt_browser import PixelatedWindow
logger = get_logger()
@@ -52,13 +54,21 @@ class MailStatusWidget(QtGui.QWidget):
self._systray = None
self._disabled = True
self._started = False
+ self._mainwindow = parent
self._unread_mails = 0
self.ui = Ui_MailStatusWidget()
self.ui.setupUi(self)
- self.ui.lblMailReadyHelp.setVisible(False)
+ self.ui.email_ready.setVisible(False)
+ self.ui.configure_button.clicked.connect(
+ self._show_configure)
+ self.ui.open_mail_button.clicked.connect(
+ self._show_pix_ua)
+ if not self._mainwindow._settings.get_pixelmail_enabled():
+ self.ui.open_mail_button.setVisible(False)
+ self.ui.or_label.setVisible(False)
# set systray tooltip status
self._mx_status = ""
@@ -144,7 +154,23 @@ class MailStatusWidget(QtGui.QWidget):
self.CONNECTED_ICON_TRAY = QtGui.QPixmap(EIP_ICONS_TRAY[1])
self.ERROR_ICON_TRAY = QtGui.QPixmap(EIP_ICONS_TRAY[2])
- # Systray and actions
+ #
+ # Button actions
+ #
+
+ def _show_configure(self):
+ pref_win = PreferencesWindow(self._mainwindow, self._mainwindow.app)
+ pref_win.set_page("email")
+ pref_win.show()
+
+ def _show_pix_ua(self):
+ win = PixelatedWindow(self._mainwindow)
+ win.show()
+ win.load_app()
+
+ #
+ # Systray
+ #
def set_systray(self, systray):
"""
@@ -166,6 +192,10 @@ class MailStatusWidget(QtGui.QWidget):
mx_status = u"{0}: {1}".format(self._service_name, self._mx_status)
self._systray.set_service_tooltip(MX_SERVICE, mx_status)
+ #
+ # Status
+ #
+
def set_action_mail_status(self, action_mail_status):
"""
Sets the action_mail_status to use.
@@ -229,6 +259,9 @@ class MailStatusWidget(QtGui.QWidget):
elif ready < 0:
tray_status = self.tr("Mail is disabled")
+ if ready < 1:
+ self._hide_mail_ready()
+
self.ui.lblMailStatusIcon.setPixmap(icon)
self._action_mail_status.setText(tray_status)
self._update_systray_tooltip()
@@ -424,9 +457,10 @@ class MailStatusWidget(QtGui.QWidget):
self._show_unread_mails()
elif event == catalog.IMAP_SERVICE_STARTED:
self._imap_started = True
- elif event == catalog.IMAP_CLIENT_LOGIN:
- # If a MUA has logged in then we don't need to show this.
- self._hide_mail_ready_help()
+ # this is disabled for now, because this event was being
+ # triggered at weird times.
+ #elif event == catalog.IMAP_CLIENT_LOGIN:
+ # self._hide_mail_ready()
if ext_status is not None:
self._set_mail_status(ext_status, ready=1)
@@ -495,15 +529,13 @@ class MailStatusWidget(QtGui.QWidget):
Display the correct UI for the connected state.
"""
self._set_mail_status(self.tr("ON"), 2)
+ self.ui.email_ready.setVisible(True)
- # this help message will hide when the MUA connects
- self.ui.lblMailReadyHelp.setVisible(True)
-
- def _hide_mail_ready_help(self):
+ def _hide_mail_ready(self):
"""
Hide the mail help message on the UI.
"""
- self.ui.lblMailReadyHelp.setVisible(False)
+ self.ui.email_ready.setVisible(False)
def mail_state_disabled(self):
"""
diff --git a/src/leap/bitmask/gui/mainwindow.py b/src/leap/bitmask/gui/mainwindow.py
index e7b849e5..6637f170 100644
--- a/src/leap/bitmask/gui/mainwindow.py
+++ b/src/leap/bitmask/gui/mainwindow.py
@@ -59,8 +59,6 @@ from leap.bitmask.util.keyring_helpers import has_keyring
from leap.common.events import register
from leap.common.events import catalog
-from .qt_browser import PixelatedWindow
-
from leap.mail.imap.service.imap import IMAP_PORT
from ui_mainwindow import Ui_MainWindow
@@ -227,11 +225,6 @@ class MainWindow(QtGui.QMainWindow, SignalTracker):
self._backend_connect()
self.ui.action_preferences.triggered.connect(self._show_preferences)
- self.ui.action_pixelated_mail.triggered.connect(
- self._show_pixelated_browser)
-
- pixelated_enabled = self._settings.get_pixelmail_enabled()
- self.ui.action_pixelated_mail.setVisible(pixelated_enabled)
self.ui.action_about_leap.triggered.connect(self._about)
self.ui.action_quit.triggered.connect(self.quit)
@@ -575,11 +568,6 @@ class MainWindow(QtGui.QMainWindow, SignalTracker):
pref_win = PreferencesWindow(self, self.app)
pref_win.show()
- def _show_pixelated_browser(self):
- win = PixelatedWindow(self)
- win.show()
- win.load_app()
-
def _update_eip_enabled_status(self, account=None, services=None):
"""
TRIGGER:
diff --git a/src/leap/bitmask/gui/preferenceswindow.py b/src/leap/bitmask/gui/preferenceswindow.py
index 82dc8d77..30091312 100644
--- a/src/leap/bitmask/gui/preferenceswindow.py
+++ b/src/leap/bitmask/gui/preferenceswindow.py
@@ -38,6 +38,12 @@ class PreferencesWindow(QtGui.QDialog):
_current_window = None # currently visible preferences window
+ _panels = {
+ "account": 0,
+ "vpn": 1,
+ "email": 2
+ }
+
def __init__(self, parent, app):
"""
:param parent: parent object of the PreferencesWindow.
@@ -240,3 +246,12 @@ class PreferencesWindow(QtGui.QDialog):
Triggered by get srp_status_logged_in, srp_status_not_logged_in
"""
self._set_account(self.app.current_account())
+
+ def set_page(self, page):
+ """
+ Jump to a particular page
+ """
+ index = PreferencesWindow._panels[page]
+ self.ui.nav_widget.setCurrentRow(index)
+ self.ui.pages_widget.setCurrentIndex(index)
+
diff --git a/src/leap/bitmask/gui/ui/mail_status.ui b/src/leap/bitmask/gui/ui/mail_status.ui
index 89e1843f..f8ebb5a8 100644
--- a/src/leap/bitmask/gui/ui/mail_status.ui
+++ b/src/leap/bitmask/gui/ui/mail_status.ui
@@ -6,12 +6,12 @@
00
- 417
- 185
+ 427
+ 157
-
+ 00
@@ -20,26 +20,131 @@
Form
-
- 0
-
+
+
+
+ color: rgb(80, 80, 80);
+
+
+ You must login to use encrypted email.
+
+
+
+
+
+
+
+ 22
+ 22
+
+
+
+
+ 22
+ 22
+
+
+
+
+
+
+ :/images/black/22/off.png
+
+
+ true
+
+
+
+
+
+
+
+ 0
+
+
+ 6
+
+
+ 0
+
+
+ 0
+
+
+
+
+
+ 0
+ 0
+
+
+
+ Configure Client
+
+
+
+
+
+
+
+ 0
+ 0
+
+
+
+ or
+
+
+ Qt::AlignCenter
+
+
+
+
+
+
+
+ 0
+ 0
+
+
+
+ Open Bitmask Mail
+
+
+
+
+
+
+ Qt::Horizontal
+
+
+ QSizePolicy::Expanding
+
+
+
+ 10
+ 10
+
+
+
+
+
+
+
-
-
-
-
- Qt::Horizontal
-
-
-
- 40
- 20
-
-
-
-
-
-
+
+
+
+
+
+ :/images/black/32/email.png
+
+
+
+
+
+
+ 0
@@ -51,89 +156,18 @@
-
-
-
+
+
+
+ Qt::Horizontal
+
+
- 24
- 24
+ 1
+ 1
-
-
-
-
- :/images/black/22/off.png
-
-
- true
-
-
-
-
-
-
- false
-
-
- background-color: #e0efd8;
-padding: 10px;
-margin-top:5px;
-
-
- QFrame::NoFrame
-
-
- QFrame::Plain
-
-
- 0
-
-
- Bitmask is ready to encrypt your email. Go to <a href="https://bitmask.net/en/help/email">https://bitmask.net/en/help/email</a> for email application setup instructions.
-
-
- Qt::AutoText
-
-
- false
-
-
- Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter
-
-
- true
-
-
- 0
-
-
- -1
-
-
- true
-
-
-
-
-
-
-
-
-
- :/images/black/32/email.png
-
-
-
-
-
-
- color: rgb(80, 80, 80);
-
-
- You must login to use encrypted email.
-
-
+
@@ -141,6 +175,7 @@ margin-top:5px;
+
diff --git a/src/leap/bitmask/gui/ui/mainwindow.ui b/src/leap/bitmask/gui/ui/mainwindow.ui
index 0dd0b891..5d8e0f35 100644
--- a/src/leap/bitmask/gui/ui/mainwindow.ui
+++ b/src/leap/bitmask/gui/ui/mainwindow.ui
@@ -75,7 +75,7 @@
00524
- 549
+ 541
@@ -306,7 +306,7 @@
00524
- 21
+ 25
@@ -315,7 +315,6 @@
-
@@ -371,11 +370,6 @@
Create a new account...
-
-
- Bitmask Mail
-
- false
diff --git a/src/leap/bitmask/gui/ui/preferences.ui b/src/leap/bitmask/gui/ui/preferences.ui
index 51cad0a1..8e884a63 100644
--- a/src/leap/bitmask/gui/ui/preferences.ui
+++ b/src/leap/bitmask/gui/ui/preferences.ui
@@ -7,7 +7,7 @@
00630
- 500
+ 560
--
cgit v1.2.3
From 2b7aafab06b1af0cad2c7f5c785bd6eea3063440 Mon Sep 17 00:00:00 2001
From: elijah
Date: Wed, 11 May 2016 17:10:43 -0700
Subject: [bug] add leap.auth to requirements-pixelated.pip
---
pkg/requirements-pixelated.pip | 1 +
1 file changed, 1 insertion(+)
diff --git a/pkg/requirements-pixelated.pip b/pkg/requirements-pixelated.pip
index d1f8004d..b3e57a1b 100644
--- a/pkg/requirements-pixelated.pip
+++ b/pkg/requirements-pixelated.pip
@@ -2,3 +2,4 @@
pixelated-user-agent
pixelated-www
whoosh
+leap.auth
\ No newline at end of file
--
cgit v1.2.3
From 6d4c24af969d72331f0177ec302b9d48381683b8 Mon Sep 17 00:00:00 2001
From: Kali Kaneko
Date: Wed, 11 May 2016 20:49:31 -0400
Subject: [style] pep8
---
src/leap/bitmask/gui/mail_status.py | 2 +-
src/leap/bitmask/gui/preferences_email_page.py | 2 +-
src/leap/bitmask/gui/preferenceswindow.py | 7 +++----
3 files changed, 5 insertions(+), 6 deletions(-)
diff --git a/src/leap/bitmask/gui/mail_status.py b/src/leap/bitmask/gui/mail_status.py
index 1045343b..cb0314b5 100644
--- a/src/leap/bitmask/gui/mail_status.py
+++ b/src/leap/bitmask/gui/mail_status.py
@@ -459,7 +459,7 @@ class MailStatusWidget(QtGui.QWidget):
self._imap_started = True
# this is disabled for now, because this event was being
# triggered at weird times.
- #elif event == catalog.IMAP_CLIENT_LOGIN:
+ # elif event == catalog.IMAP_CLIENT_LOGIN:
# self._hide_mail_ready()
if ext_status is not None:
diff --git a/src/leap/bitmask/gui/preferences_email_page.py b/src/leap/bitmask/gui/preferences_email_page.py
index 0f44dfee..93c77df1 100644
--- a/src/leap/bitmask/gui/preferences_email_page.py
+++ b/src/leap/bitmask/gui/preferences_email_page.py
@@ -121,7 +121,7 @@ class PreferencesEmailPage(PreferencesPage):
webmail_enabled = self.settings.get_pixelmail_enabled()
self.ui.webmail_checkbox.setChecked(webmail_enabled)
if not HAS_PIXELATED:
- self.ui.webmail_box.setVisible(False)
+ self.ui.webmail_box.setVisible(False)
self.ui.import_button.setVisible(False) # hide this until working
self.ui.message_label.setVisible(False)
self.ui.email_tabs.setVisible(True)
diff --git a/src/leap/bitmask/gui/preferenceswindow.py b/src/leap/bitmask/gui/preferenceswindow.py
index 30091312..50a972e1 100644
--- a/src/leap/bitmask/gui/preferenceswindow.py
+++ b/src/leap/bitmask/gui/preferenceswindow.py
@@ -39,9 +39,9 @@ class PreferencesWindow(QtGui.QDialog):
_current_window = None # currently visible preferences window
_panels = {
- "account": 0,
- "vpn": 1,
- "email": 2
+ "account": 0,
+ "vpn": 1,
+ "email": 2
}
def __init__(self, parent, app):
@@ -254,4 +254,3 @@ class PreferencesWindow(QtGui.QDialog):
index = PreferencesWindow._panels[page]
self.ui.nav_widget.setCurrentRow(index)
self.ui.pages_widget.setCurrentIndex(index)
-
--
cgit v1.2.3
From 13b5afd1bdea38e908bb774becfc0f49a532d5bd Mon Sep 17 00:00:00 2001
From: Kali Kaneko
Date: Wed, 11 May 2016 13:38:07 -0400
Subject: [feat] resize qt-browser to a sensible default
mainly to avoid the "Send" button to become out of view in the Compose
pane (it needed scrolling to get it on view).
this resize shouldn't be needed when pixelated solves the
size-responsiveness issue.
---
src/leap/bitmask/gui/qt_browser.py | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/src/leap/bitmask/gui/qt_browser.py b/src/leap/bitmask/gui/qt_browser.py
index 2f7e6086..2d9e20e6 100644
--- a/src/leap/bitmask/gui/qt_browser.py
+++ b/src/leap/bitmask/gui/qt_browser.py
@@ -37,6 +37,11 @@ class PixelatedWindow(QtGui.QDialog):
self.setLayout(layout)
self.setWindowTitle('Bitmask Mail')
+ # For the moment, we need to resize to a sensible default to avoid the
+ # "send" button to be out of view in the compose pane. This should be
+ # removed as soon as pixelated becomes size-responsive.
+ self.resize(800, 700)
+
def load_app(self):
self.view.load(QtCore.QUrl(PIXELATED_URI))
self.view.page().setForwardUnsupportedContent(True)
--
cgit v1.2.3
From cba8beb034eade7951ca08b69a152fc76c4362a5 Mon Sep 17 00:00:00 2001
From: Kali Kaneko
Date: Wed, 11 May 2016 20:51:16 -0400
Subject: [pkg] bump bundle to rc4
---
pkg/next-version | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/pkg/next-version b/pkg/next-version
index 29a0f215..c29ffb37 100644
--- a/pkg/next-version
+++ b/pkg/next-version
@@ -1 +1 @@
-0.9.2.rc2
+0.9.2.rc4
--
cgit v1.2.3
From e5cf9ff70cc27cbbf17b9e3c4df98d336d0ed0af Mon Sep 17 00:00:00 2001
From: Kali Kaneko
Date: Fri, 13 May 2016 11:55:48 -0400
Subject: [pkg] fold in changelog
---
CHANGELOG.rst | 32 ++++++++++++++++++++++++++++++++
changes/next-changelog.rst | 18 ------------------
2 files changed, 32 insertions(+), 18 deletions(-)
diff --git a/CHANGELOG.rst b/CHANGELOG.rst
index 1c8422fa..3974b120 100644
--- a/CHANGELOG.rst
+++ b/CHANGELOG.rst
@@ -3,6 +3,38 @@
Changelog
---------
+0.9.2 May 13 - "panis et circenses"
++++++++++++++++++++++++++++++++++++++++++++
+
+Features
+~~~~~~~~
+- `#7552 `_: Improve UI message and add some margin above the msg box.
+- `#7656 `_: Adapt to multi-user aware events.
+- `#4469 `_: Display randomly generated service token on the Help Window.
+- `#6041 `_: Write service tokens to a file to allow email clients to read them from there.
+- Use cred-based authentication on SMTP.
+- Add email panel to preferences window.
+- Ability to launch detached bitmask.core daemon, and a simplistic bitmask_cli. Not used by the main client yet.
+- Experimental support for the Pixelated User Agent, branded as "Bitmask Mail".
+
+Bugfixes
+~~~~~~~~
+- `#7568 `_: Fix typo on signal name.
+- `#7583 `_: Fix set_soledad_auth_token event callback signature.
+- `#7585 `_: Open email help link on browser.
+- `#7598 `_: Fix errback on InvalidAuthToken.
+- `#7869 `_: Redownload smtp certificate if needed.
+- Do not translate 'https' text on QLabel.
+
+Misc
+~~~~
+- PyInstaller based new style of bundles.
+
+Known Issues
+~~~~~~~~~~~~
+- `#8057 `_: Logging out twice produces a segfault in Qt
+- `#1236 `_: Description of the known issue corresponding with issue #1236.
+
0.9.1 November 03 - "the day of the calaca"
+++++++++++++++++++++++++++++++++++++++++++
diff --git a/changes/next-changelog.rst b/changes/next-changelog.rst
index 8a5035ff..59f68d8d 100644
--- a/changes/next-changelog.rst
+++ b/changes/next-changelog.rst
@@ -10,27 +10,11 @@ I've added a new category `Misc` so we can track doc/style/packaging stuff.
Features
~~~~~~~~
-- `#7552 `_: Improve UI message and add some margin above the msg box.
-- `#7656 `_: Adapt to multi-user aware events.
-- `#4469 `_: Display randomly generated service token on the Help Window.
-- `#6041 `_: Write service tokens to a file to allow email clients to read them from there.
-- Use cred-based authentication on SMTP.
-- Experimental support for the Pixelated WebMail.
-- Add email panel to preferences window.
-- Ability to launch detached bitmask.core daemon, and a simplistic bitmask_cli. Not used by the main client yet.
-
- `#1234 `_: Description of the new feature corresponding with issue #1234.
- New feature without related issue number.
Bugfixes
~~~~~~~~
-- `#7568 `_: Fix typo on signal name.
-- `#7583 `_: Fix set_soledad_auth_token event callback signature.
-- `#7585 `_: Open email help link on browser.
-- `#7598 `_: Fix errback on InvalidAuthToken.
-- `#7869 `_: Redownload smtp certificate if needed.
-- Do not translate 'https' text on QLabel.
-
- `#1235 `_: Description for the fixed stuff corresponding with issue #1235.
- Bugfix without related issue number.
@@ -41,5 +25,3 @@ Misc
Known Issues
~~~~~~~~~~~~
-- `#8057 `_: Logging out twice produces a segfault in Qt
-- `#1236 `_: Description of the known issue corresponding with issue #1236.
--
cgit v1.2.3
From facefed990195bd89bf1064e75b171edd084f632 Mon Sep 17 00:00:00 2001
From: Kali Kaneko
Date: Wed, 18 May 2016 06:23:06 -0400
Subject: [pkg] bump version to 0.9.2 final
---
pkg/next-version | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/pkg/next-version b/pkg/next-version
index c29ffb37..2003b639 100644
--- a/pkg/next-version
+++ b/pkg/next-version
@@ -1 +1 @@
-0.9.2.rc4
+0.9.2
--
cgit v1.2.3