Merge pull request #162 from atom/cj-replace-sparkle-with-squirrel

Replace sparkle with squirrel
This commit is contained in:
Cheng Zhao 2014-02-02 04:56:13 -08:00
commit 9f0d9e0fad
12 changed files with 159 additions and 238 deletions

View file

@ -65,7 +65,6 @@
'browser/api/atom_browser_bindings.h', 'browser/api/atom_browser_bindings.h',
'browser/auto_updater.cc', 'browser/auto_updater.cc',
'browser/auto_updater.h', 'browser/auto_updater.h',
'browser/auto_updater_delegate.cc',
'browser/auto_updater_delegate.h', 'browser/auto_updater_delegate.h',
'browser/auto_updater_mac.mm', 'browser/auto_updater_mac.mm',
'browser/auto_updater_win.cc', 'browser/auto_updater_win.cc',
@ -198,13 +197,6 @@
], ],
}], # OS=="win" }], # OS=="win"
], ],
'fix_framework_link_command': [
'install_name_tool',
'-change',
'@loader_path/../Frameworks/Sparkle.framework/Versions/A/Sparkle',
'@rpath/Sparkle.framework/Versions/A/Sparkle',
'${BUILT_PRODUCTS_DIR}/${EXECUTABLE_PATH}'
],
'atom_source_root': '<!(python tools/atom_source_root.py)', 'atom_source_root': '<!(python tools/atom_source_root.py)',
}, },
'target_defaults': { 'target_defaults': {
@ -263,7 +255,9 @@
'files': [ 'files': [
'<(PRODUCT_DIR)/<(product_name) Helper.app', '<(PRODUCT_DIR)/<(product_name) Helper.app',
'<(PRODUCT_DIR)/<(framework_name).framework', '<(PRODUCT_DIR)/<(framework_name).framework',
'frameworks/Sparkle.framework', 'frameworks/Squirrel.framework',
'frameworks/ReactiveCocoa.framework',
'frameworks/Mantle.framework',
], ],
}, },
{ {
@ -274,12 +268,6 @@
}, },
], ],
'postbuilds': [ 'postbuilds': [
{
'postbuild_name': 'Fix Framework Link',
'action': [
'<@(fix_framework_link_command)',
],
},
{ {
# This postbuid step is responsible for creating the following # This postbuid step is responsible for creating the following
# helpers: # helpers:
@ -494,7 +482,9 @@
'link_settings': { 'link_settings': {
'libraries': [ 'libraries': [
'$(SDKROOT)/System/Library/Frameworks/Carbon.framework', '$(SDKROOT)/System/Library/Frameworks/Carbon.framework',
'frameworks/Sparkle.framework', 'frameworks/Squirrel.framework',
'frameworks/ReactiveCocoa.framework',
'frameworks/Mantle.framework',
], ],
}, },
'mac_bundle': 1, 'mac_bundle': 1,
@ -532,12 +522,6 @@
}, },
], ],
'postbuilds': [ 'postbuilds': [
{
'postbuild_name': 'Fix Framework Link',
'action': [
'<@(fix_framework_link_command)',
],
},
{ {
'postbuild_name': 'Add symlinks for framework subdirectories', 'postbuild_name': 'Add symlinks for framework subdirectories',
'action': [ 'action': [
@ -569,14 +553,6 @@
'@executable_path/../../..', '@executable_path/../../..',
], ],
}, },
'postbuilds': [
{
'postbuild_name': 'Fix Framework Link',
'action': [
'<@(fix_framework_link_command)',
],
},
],
}, # target helper }, # target helper
], ],
}], # OS==Mac }], # OS==Mac

View file

@ -4,6 +4,7 @@
#include "browser/api/atom_api_auto_updater.h" #include "browser/api/atom_api_auto_updater.h"
#include "base/time/time.h"
#include "base/values.h" #include "base/values.h"
#include "browser/auto_updater.h" #include "browser/auto_updater.h"
#include "common/v8/native_type_conversions.h" #include "common/v8/native_type_conversions.h"
@ -17,32 +18,43 @@ namespace api {
AutoUpdater::AutoUpdater(v8::Handle<v8::Object> wrapper) AutoUpdater::AutoUpdater(v8::Handle<v8::Object> wrapper)
: EventEmitter(wrapper) { : EventEmitter(wrapper) {
auto_updater::AutoUpdater::SetDelegate(this); auto_updater::AutoUpdater::SetDelegate(this);
auto_updater::AutoUpdater::Init();
} }
AutoUpdater::~AutoUpdater() { AutoUpdater::~AutoUpdater() {
auto_updater::AutoUpdater::SetDelegate(NULL); auto_updater::AutoUpdater::SetDelegate(NULL);
} }
void AutoUpdater::WillInstallUpdate(const std::string& version, void AutoUpdater::OnError(const std::string& error) {
const base::Closure& install) {
continue_update_ = install;
base::ListValue args; base::ListValue args;
args.AppendString(version); args.AppendString(error);
bool prevent_default = Emit("will-install-update-raw", &args); Emit("error", &args);
if (!prevent_default)
install.Run();
} }
void AutoUpdater::ReadyForUpdateOnQuit(const std::string& version, void AutoUpdater::OnCheckingForUpdate() {
Emit("checking-for-update");
}
void AutoUpdater::OnUpdateAvailable() {
Emit("update-available");
}
void AutoUpdater::OnUpdateNotAvailable() {
Emit("update-not-available");
}
void AutoUpdater::OnUpdateDownloaded(const std::string& release_notes,
const std::string& release_name,
const base::Time& release_date,
const std::string& update_url,
const base::Closure& quit_and_install) { const base::Closure& quit_and_install) {
quit_and_install_ = quit_and_install; quit_and_install_ = quit_and_install;
base::ListValue args; base::ListValue args;
args.AppendString(version); args.AppendString(release_notes);
Emit("ready-for-update-on-quit-raw", &args); args.AppendString(release_name);
args.AppendDouble(release_date.ToJsTime());
args.AppendString(update_url);
Emit("update-downloaded-raw", &args);
} }
// static // static
@ -58,39 +70,12 @@ void AutoUpdater::SetFeedURL(const v8::FunctionCallbackInfo<v8::Value>& args) {
auto_updater::AutoUpdater::SetFeedURL(FromV8Value(args[0])); auto_updater::AutoUpdater::SetFeedURL(FromV8Value(args[0]));
} }
// static
void AutoUpdater::SetAutomaticallyChecksForUpdates(
const v8::FunctionCallbackInfo<v8::Value>& args) {
auto_updater::AutoUpdater::SetAutomaticallyChecksForUpdates(
FromV8Value(args[0]));
}
// static
void AutoUpdater::SetAutomaticallyDownloadsUpdates(
const v8::FunctionCallbackInfo<v8::Value>& args) {
auto_updater::AutoUpdater::SetAutomaticallyDownloadsUpdates(
FromV8Value(args[0]));
}
// static // static
void AutoUpdater::CheckForUpdates( void AutoUpdater::CheckForUpdates(
const v8::FunctionCallbackInfo<v8::Value>& args) { const v8::FunctionCallbackInfo<v8::Value>& args) {
auto_updater::AutoUpdater::CheckForUpdates(); auto_updater::AutoUpdater::CheckForUpdates();
} }
// static
void AutoUpdater::CheckForUpdatesInBackground(
const v8::FunctionCallbackInfo<v8::Value>& args) {
auto_updater::AutoUpdater::CheckForUpdatesInBackground();
}
// static
void AutoUpdater::ContinueUpdate(
const v8::FunctionCallbackInfo<v8::Value>& args) {
AutoUpdater* self = AutoUpdater::Unwrap<AutoUpdater>(args.This());
self->continue_update_.Run();
}
// static // static
void AutoUpdater::QuitAndInstall( void AutoUpdater::QuitAndInstall(
const v8::FunctionCallbackInfo<v8::Value>& args) { const v8::FunctionCallbackInfo<v8::Value>& args) {
@ -106,18 +91,7 @@ void AutoUpdater::Initialize(v8::Handle<v8::Object> target) {
t->SetClassName(v8::String::NewSymbol("AutoUpdater")); t->SetClassName(v8::String::NewSymbol("AutoUpdater"));
NODE_SET_PROTOTYPE_METHOD(t, "setFeedUrl", SetFeedURL); NODE_SET_PROTOTYPE_METHOD(t, "setFeedUrl", SetFeedURL);
NODE_SET_PROTOTYPE_METHOD(t,
"setAutomaticallyChecksForUpdates",
SetAutomaticallyChecksForUpdates);
NODE_SET_PROTOTYPE_METHOD(t,
"setAutomaticallyDownloadsUpdates",
SetAutomaticallyDownloadsUpdates);
NODE_SET_PROTOTYPE_METHOD(t, "checkForUpdates", CheckForUpdates); NODE_SET_PROTOTYPE_METHOD(t, "checkForUpdates", CheckForUpdates);
NODE_SET_PROTOTYPE_METHOD(t,
"checkForUpdatesInBackground",
CheckForUpdatesInBackground);
NODE_SET_PROTOTYPE_METHOD(t, "continueUpdate", ContinueUpdate);
NODE_SET_PROTOTYPE_METHOD(t, "quitAndInstall", QuitAndInstall); NODE_SET_PROTOTYPE_METHOD(t, "quitAndInstall", QuitAndInstall);
target->Set(v8::String::NewSymbol("AutoUpdater"), t->GetFunction()); target->Set(v8::String::NewSymbol("AutoUpdater"), t->GetFunction());

View file

@ -24,28 +24,27 @@ class AutoUpdater : public EventEmitter,
protected: protected:
explicit AutoUpdater(v8::Handle<v8::Object> wrapper); explicit AutoUpdater(v8::Handle<v8::Object> wrapper);
virtual void WillInstallUpdate(const std::string& version, // AutoUpdaterDelegate implementations.
const base::Closure& install) OVERRIDE; virtual void OnError(const std::string& error) OVERRIDE;
virtual void ReadyForUpdateOnQuit( virtual void OnCheckingForUpdate() OVERRIDE;
const std::string& version, virtual void OnUpdateAvailable() OVERRIDE;
virtual void OnUpdateNotAvailable() OVERRIDE;
virtual void OnUpdateDownloaded(
const std::string& release_notes,
const std::string& release_name,
const base::Time& release_date,
const std::string& update_url,
const base::Closure& quit_and_install) OVERRIDE; const base::Closure& quit_and_install) OVERRIDE;
private: private:
static void New(const v8::FunctionCallbackInfo<v8::Value>& args); static void New(const v8::FunctionCallbackInfo<v8::Value>& args);
static void SetFeedURL(const v8::FunctionCallbackInfo<v8::Value>& args); static void SetFeedURL(const v8::FunctionCallbackInfo<v8::Value>& args);
static void SetAutomaticallyChecksForUpdates(
const v8::FunctionCallbackInfo<v8::Value>& args);
static void SetAutomaticallyDownloadsUpdates(
const v8::FunctionCallbackInfo<v8::Value>& args);
static void CheckForUpdates(const v8::FunctionCallbackInfo<v8::Value>& args); static void CheckForUpdates(const v8::FunctionCallbackInfo<v8::Value>& args);
static void CheckForUpdatesInBackground(
const v8::FunctionCallbackInfo<v8::Value>& args);
static void ContinueUpdate(const v8::FunctionCallbackInfo<v8::Value>& args); static void ContinueUpdate(const v8::FunctionCallbackInfo<v8::Value>& args);
static void QuitAndInstall(const v8::FunctionCallbackInfo<v8::Value>& args); static void QuitAndInstall(const v8::FunctionCallbackInfo<v8::Value>& args);
base::Closure continue_update_;
base::Closure quit_and_install_; base::Closure quit_and_install_;
DISALLOW_COPY_AND_ASSIGN(AutoUpdater); DISALLOW_COPY_AND_ASSIGN(AutoUpdater);

View file

@ -4,9 +4,8 @@ EventEmitter = require('events').EventEmitter
AutoUpdater::__proto__ = EventEmitter.prototype AutoUpdater::__proto__ = EventEmitter.prototype
autoUpdater = new AutoUpdater autoUpdater = new AutoUpdater
autoUpdater.on 'will-install-update-raw', (event, version) -> autoUpdater.on 'update-downloaded-raw', (args...) ->
@emit 'will-install-update', event, version, => @continueUpdate() args[2] = new Date(args[2]) # releaseDate
autoUpdater.on 'ready-for-update-on-quit-raw', (event, version) -> @emit 'update-downloaded', args..., => @quitAndInstall()
@emit 'ready-for-update-on-quit', event, version, => @quitAndInstall()
module.exports = autoUpdater module.exports = autoUpdater

View file

@ -19,13 +19,8 @@ class AutoUpdater {
static AutoUpdaterDelegate* GetDelegate(); static AutoUpdaterDelegate* GetDelegate();
static void SetDelegate(AutoUpdaterDelegate* delegate); static void SetDelegate(AutoUpdaterDelegate* delegate);
static void Init();
static void SetFeedURL(const std::string& url); static void SetFeedURL(const std::string& url);
static void SetAutomaticallyChecksForUpdates(bool yes);
static void SetAutomaticallyDownloadsUpdates(bool yes);
static void CheckForUpdates(); static void CheckForUpdates();
static void CheckForUpdatesInBackground();
private: private:
static AutoUpdaterDelegate* delegate_; static AutoUpdaterDelegate* delegate_;

View file

@ -1,21 +0,0 @@
// Copyright (c) 2013 GitHub, Inc. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "browser/auto_updater_delegate.h"
#include "base/callback.h"
namespace auto_updater {
void AutoUpdaterDelegate::WillInstallUpdate(const std::string& version,
const base::Closure& install) {
install.Run();
}
void AutoUpdaterDelegate::ReadyForUpdateOnQuit(
const std::string& version,
const base::Closure& quit_and_install) {
}
} // namespace auto_updater

View file

@ -9,17 +9,32 @@
#include "base/callback_forward.h" #include "base/callback_forward.h"
namespace base {
class Time;
}
namespace auto_updater { namespace auto_updater {
class AutoUpdaterDelegate { class AutoUpdaterDelegate {
public: public:
// The application is going to relaunch to install update. // An error happened.
virtual void WillInstallUpdate(const std::string& version, virtual void OnError(const std::string& error) {}
const base::Closure& install);
// User has chosen to update on quit. // Checking to see if there is an update
virtual void ReadyForUpdateOnQuit(const std::string& version, virtual void OnCheckingForUpdate() {}
const base::Closure& quit_and_install);
// There is an update available and it is being downloaded
virtual void OnUpdateAvailable() {}
// There is no available update.
virtual void OnUpdateNotAvailable() {}
// There is a new update which has been downloaded.
virtual void OnUpdateDownloaded(const std::string& release_notes,
const std::string& release_name,
const base::Time& release_date,
const std::string& update_url,
const base::Closure& quit_and_install) {}
protected: protected:
virtual ~AutoUpdaterDelegate() {} virtual ~AutoUpdaterDelegate() {}

View file

@ -4,106 +4,87 @@
#include "browser/auto_updater.h" #include "browser/auto_updater.h"
// Sparkle's headers are throwing compilation warnings, supress them. #import <ReactiveCocoa/RACCommand.h>
#pragma GCC diagnostic ignored "-Wmissing-method-return-type" #import <ReactiveCocoa/RACSignal.h>
#import <Sparkle/Sparkle.h> #import <ReactiveCocoa/NSObject+RACPropertySubscribing.h>
#import <Squirrel/Squirrel.h>
#include "base/bind.h" #include "base/bind.h"
#include "base/memory/scoped_ptr.h" #include "base/time/time.h"
#include "base/strings/sys_string_conversions.h" #include "base/strings/sys_string_conversions.h"
#include "browser/auto_updater_delegate.h" #include "browser/auto_updater_delegate.h"
using auto_updater::AutoUpdaterDelegate; namespace auto_updater {
namespace { namespace {
struct NSInvocationDeleter { // The gloal SQRLUpdater object.
inline void operator()(NSInvocation* invocation) const { SQRLUpdater* g_updater = nil;
[invocation release];
}
};
typedef scoped_ptr<NSInvocation, NSInvocationDeleter> ScopedNSInvocation; void RelaunchToInstallUpdate() {
[[g_updater relaunchToInstallUpdate] subscribeError:^(NSError* error) {
// We are passing the NSInvocation as scoped_ptr, because we want to make sure AutoUpdaterDelegate* delegate = AutoUpdater::GetDelegate();
// whether or not the callback is called, the NSInvocation should alwasy be if (delegate)
// released, the only way to ensure it is to use scoped_ptr. delegate->OnError(base::SysNSStringToUTF8(error.localizedDescription));
void CallNSInvocation(ScopedNSInvocation invocation) { }];
[invocation.get() invoke];
} }
} // namespace } // namespace
@interface SUUpdaterDelegate : NSObject { // static
} void AutoUpdater::SetFeedURL(const std::string& feed) {
@end if (g_updater == nil) {
// Initialize the SQRLUpdater.
NSURL* url = [NSURL URLWithString:base::SysUTF8ToNSString(feed)];
NSURLRequest* urlRequest = [NSURLRequest requestWithURL:url];
g_updater = [[SQRLUpdater alloc] initWithUpdateRequest:urlRequest];
@implementation SUUpdaterDelegate AutoUpdaterDelegate* delegate = GetDelegate();
- (BOOL)updater:(SUUpdater*)updater
shouldPostponeRelaunchForUpdate:(SUAppcastItem*)update
untilInvoking:(NSInvocation*)invocation {
AutoUpdaterDelegate* delegate = auto_updater::AutoUpdater::GetDelegate();
if (!delegate)
return NO;
std::string version(base::SysNSStringToUTF8([update versionString]));
ScopedNSInvocation invocation_ptr([invocation retain]);
delegate->WillInstallUpdate(
version,
base::Bind(&CallNSInvocation, base::Passed(invocation_ptr.Pass())));
return YES;
}
- (void)updater:(SUUpdater*)updater
willInstallUpdateOnQuit:(SUAppcastItem*)update
immediateInstallationInvocation:(NSInvocation*)invocation {
AutoUpdaterDelegate* delegate = auto_updater::AutoUpdater::GetDelegate();
if (!delegate) if (!delegate)
return; return;
std::string version(base::SysNSStringToUTF8([update versionString])); [[g_updater rac_valuesForKeyPath:@"state" observer:g_updater]
ScopedNSInvocation invocation_ptr([invocation retain]); subscribeNext:^(NSNumber *stateNumber) {
delegate->ReadyForUpdateOnQuit( int state = [stateNumber integerValue];
version, if (state == SQRLUpdaterStateCheckingForUpdate) {
base::Bind(&CallNSInvocation, base::Passed(invocation_ptr.Pass()))); delegate->OnCheckingForUpdate();
} else if (state == SQRLUpdaterStateDownloadingUpdate) {
delegate->OnUpdateAvailable();
} }
}];
@end
namespace auto_updater {
// static
void AutoUpdater::Init() {
SUUpdaterDelegate* delegate = [[SUUpdaterDelegate alloc] init];
[[SUUpdater sharedUpdater] setDelegate:delegate];
} }
// static
void AutoUpdater::SetFeedURL(const std::string& url) {
NSString* url_str(base::SysUTF8ToNSString(url));
[[SUUpdater sharedUpdater] setFeedURL:[NSURL URLWithString:url_str]];
}
// static
void AutoUpdater::SetAutomaticallyChecksForUpdates(bool yes) {
[[SUUpdater sharedUpdater] setAutomaticallyChecksForUpdates:yes];
}
// static
void AutoUpdater::SetAutomaticallyDownloadsUpdates(bool yes) {
[[SUUpdater sharedUpdater] setAutomaticallyDownloadsUpdates:yes];
} }
// static // static
void AutoUpdater::CheckForUpdates() { void AutoUpdater::CheckForUpdates() {
[[SUUpdater sharedUpdater] checkForUpdates:nil]; AutoUpdaterDelegate* delegate = GetDelegate();
} if (!delegate)
return;
// static [[[[g_updater.checkForUpdatesCommand
void AutoUpdater::CheckForUpdatesInBackground() { execute:nil]
[[SUUpdater sharedUpdater] checkForUpdatesInBackground]; // Send a `nil` after everything...
concat:[RACSignal return:nil]]
// But only take the first value. If an update is sent, we'll get that.
// Otherwise, we'll get our inserted `nil` value.
take:1]
subscribeNext:^(SQRLDownloadedUpdate *downloadedUpdate) {
if (downloadedUpdate) {
SQRLUpdate* update = downloadedUpdate.update;
// There is a new update that has been downloaded.
delegate->OnUpdateDownloaded(
base::SysNSStringToUTF8(update.releaseNotes),
base::SysNSStringToUTF8(update.releaseName),
base::Time::FromDoubleT(update.releaseDate.timeIntervalSince1970),
base::SysNSStringToUTF8(update.updateURL.absoluteString),
base::Bind(RelaunchToInstallUpdate));
} else {
// When the completed event is sent with no update, then we know there
// is no update available.
delegate->OnUpdateNotAvailable();
}
} error:^(NSError *error) {
delegate->OnError(base::SysNSStringToUTF8(error.localizedDescription));
}];
} }
} // namespace auto_updater } // namespace auto_updater

View file

@ -1,42 +1,42 @@
# auto-updater # auto-updater
`auto-updater` module is a simple wrap around the Sparkle framework, it The `auto-updater` module is a simple wrap around the
provides auto update service for the application. [Squirrel](https://github.com/Squirrel/Squirrel.Mac) framework, you should
follow Squirrel's instructions on setting the server.
Before using this module, you should edit the `Info.plist` following ## Event: checking-for-update
https://github.com/andymatuschak/Sparkle/wiki.
## Event: will-install-update Emitted when checking for update has started.
## Event: update-available
Emitted when there is an available update, the update would be downloaded
automatically.
## Event: update-not-available
Emitted when there is no available update.
## Event: update-downloaded
* `event` Event * `event` Event
* `version` String * `releaseNotes` String
* `continueUpdate` Function * `releaseName` String
* `releaseDate` Date
This event is emitted when the update is found and going to be installed. * `updateUrl` String
Calling `event.preventDefault()` would pause it, and you can call
`continueUpdate` to continue the update.
## Event: ready-for-update-on-quit
* `event` Event
* `version` String
* `quitAndUpdate` Function * `quitAndUpdate` Function
This event is emitted when user chose to delay the update until the quit. Emitted when update has been downloaded, calling `quitAndUpdate()` would restart
Calling `quitAndUpdate()` would quit the application and install the update. the application and install the update.
## autoUpdater.setFeedUrl(url) ## autoUpdater.setFeedUrl(url)
* `url` String * `url` String
## autoUpdater.setAutomaticallyChecksForUpdates(flag) Set the `url` and initialize the auto updater. The `url` could not be changed
once it is set.
* `flag` Boolean
## autoUpdater.setAutomaticallyDownloadsUpdates(flag)
* `flag` Boolean
## autoUpdater.checkForUpdates() ## autoUpdater.checkForUpdates()
## autoUpdater.checkForUpdatesInBackground() Ask the server whether there is an update, you have to call `setFeedUrl` before
using this API.

View file

@ -13,6 +13,7 @@ SOURCE_ROOT = os.path.abspath(os.path.dirname(os.path.dirname(__file__)))
def main(): def main():
rm_rf(os.path.join(SOURCE_ROOT, 'out')) rm_rf(os.path.join(SOURCE_ROOT, 'out'))
rm_rf(os.path.join(SOURCE_ROOT, 'node_modules')) rm_rf(os.path.join(SOURCE_ROOT, 'node_modules'))
rm_rf(os.path.join(SOURCE_ROOT, 'frameworks'))
rm_rf(os.path.join(SOURCE_ROOT, 'vendor', 'brightray', 'vendor', 'download', rm_rf(os.path.join(SOURCE_ROOT, 'vendor', 'brightray', 'vendor', 'download',
'libchromiumcontent')) 'libchromiumcontent'))

2
script/cpplint.py vendored
View file

@ -6,10 +6,10 @@ import subprocess
import sys import sys
IGNORE_FILES = [ IGNORE_FILES = [
'app/win/resource.h',
'browser/atom_application_mac.h', 'browser/atom_application_mac.h',
'browser/atom_application_delegate_mac.h', 'browser/atom_application_delegate_mac.h',
'browser/native_window_mac.h', 'browser/native_window_mac.h',
'browser/resources/win/resource.h',
'browser/ui/cocoa/event_processing_window.h', 'browser/ui/cocoa/event_processing_window.h',
'browser/ui/cocoa/atom_menu_controller.h', 'browser/ui/cocoa/atom_menu_controller.h',
'browser/ui/cocoa/nsalert_synchronous_sheet.h', 'browser/ui/cocoa/nsalert_synchronous_sheet.h',

View file

@ -7,13 +7,15 @@ from lib.util import safe_mkdir, extract_zip, tempdir, download
SOURCE_ROOT = os.path.abspath(os.path.dirname(os.path.dirname(__file__))) SOURCE_ROOT = os.path.abspath(os.path.dirname(os.path.dirname(__file__)))
FRAMEWORKS_URL = 'https://gh-contractor-zcbenz.s3.amazonaws.com/frameworks' FRAMEWORKS_URL = 'http://atom-alpha.s3.amazonaws.com'
def main(): def main():
os.chdir(SOURCE_ROOT) os.chdir(SOURCE_ROOT)
safe_mkdir('frameworks') safe_mkdir('frameworks')
download_and_unzip('Sparkle') download_and_unzip('Mantle')
download_and_unzip('ReactiveCocoa')
download_and_unzip('Squirrel')
def download_and_unzip(framework): def download_and_unzip(framework):