Skip to content

Commit

Permalink
Fix #347 - add bramble.export() for creating project.zip, an archive …
Browse files Browse the repository at this point in the history
…of entire fs
  • Loading branch information
humphd committed Aug 11, 2015
1 parent 858768d commit 6e12211
Show file tree
Hide file tree
Showing 5 changed files with 33 additions and 45 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -316,6 +316,7 @@ to be notified when the action completes:
* `addNewFile([ext, callback])` - adds a new file, using the optional `ext` as an extension if provided.
* `addNewFileWithContents(filename, contents[, callback])` - adds a new file to the mounted project's root dir with the given `filename` and `contents` (`Filer.Buffer` or `String`).
* `addNewFolder([callback])` - adds a new folder.
* `export([callback])` - creates an archive `.zip` file of the entire project's filesystem, and downloads it to the browser.

## Bramble Instance Events

Expand Down
4 changes: 4 additions & 0 deletions src/bramble/client/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -709,5 +709,9 @@ define([
this._executeRemoteCommand({commandCategory: "brackets", command: "FILE_FOLDER"}, callback);
};

BrambleProxy.prototype.export = function(callback) {
this._executeRemoteCommand({commandCategory: "bramble", command: "BRAMBLE_EXPORT"}, callback);
};

return Bramble;
});
5 changes: 5 additions & 0 deletions src/extensions/default/bramble/lib/RemoteCommandHandler.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ define(function (require, exports, module) {
var PreferencesManager = brackets.getModule("preferences/PreferencesManager");
var _ = brackets.getModule("thirdparty/lodash");
var BracketsFiler = brackets.getModule("filesystem/impls/filer/BracketsFiler");
var ArchiveUtils = brackets.getModule("filesystem/impls/filer/ArchiveUtils");
var Path = BracketsFiler.Path;
var FilerBuffer = BracketsFiler.Buffer;
var StartupState = brackets.getModule("bramble/StartupState");
Expand Down Expand Up @@ -147,6 +148,10 @@ define(function (require, exports, module) {
}
);
break;
case "BRAMBLE_EXPORT":
skipCallback = true;
ArchiveUtils.archive(callback);
break;
case "RESIZE":
// The host window was resized, update all panes
WorkspaceManager.recomputeLayout(true);
Expand Down
66 changes: 21 additions & 45 deletions src/filesystem/impls/filer/ArchiveUtils.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@

/*jslint vars: true, plusplus: true, devel: true, nomen: true, indent: 4, maxerr: 50 */
/*global define, Worker */
/*global define, Blob, Worker */

define(function (require, exports, module) {
"use strict";
Expand All @@ -12,6 +12,7 @@ define(function (require, exports, module) {
var JSZip = require("thirdparty/jszip/dist/jszip.min");
var BlobUtils = require("filesystem/impls/filer/BlobUtils");
var Filer = require("filesystem/impls/filer/BracketsFiler");
var saveAs = require("thirdparty/FileSaver");
var Buffer = Filer.Buffer;
var Path = Filer.Path;
var fs = Filer.fs();
Expand Down Expand Up @@ -141,51 +142,31 @@ define(function (require, exports, module) {
}
}

function zip(zipfile, paths, options, callback) {
if(typeof options === 'function') {
callback = options;
options = {};
}
options = options || {};
callback = callback || function(){};

if(!zipfile) {
return callback(new Error("missing zipfile argument"));
}
if(!paths) {
return callback(new Error("missing paths argument"));
}
if(typeof paths === "string") {
paths = [paths];
}

// Zip the entire project, starting at the project root.
function archive(callback) {
var root = StartupState.project("root");
zipfile = Path.resolve(root, zipfile);
var rootRegex = new RegExp("^" + root + "\/?");

function toRelPath(path) {
// Make path relative within the zip
return path.replace(/^\//, '');
function toRelProjectPath(path) {
// Make path relative within the zip, rooted in a `project/` dir
return path.replace(rootRegex, "project/");
}

function addFile(path, callback) {
fs.readFile(path, function(err, data) {
fs.readFile(path, {encoding: null}, function(err, data) {
if(err) {
return callback(err);
}

archive.file(toRelPath(path), data.buffer, {binary: true});
jszip.file(toRelProjectPath(path), data.buffer, {binary: true});
callback();
});
}

function addDir(path, callback) {
fs.readdir(path, function(err, list) {
// Add the directory itself
archive.folder(toRelPath(path));

if(!options.recursive) {
return callback();
}
jszip.folder(toRelProjectPath(path));

// Add all children of this dir, too
async.eachSeries(list, function(entry, callback) {
Expand All @@ -210,22 +191,17 @@ define(function (require, exports, module) {
});
}

var archive = new JSZip();

// Make sure the zipfile doesn't already exist.
fs.exists(zipfile, function(exists) {
if(exists) {
return callback(new Error('zipfile already exists', zipfile));
// TODO: we should try to move this to a worker
var jszip = new JSZip();
add(root, function(err) {
if(err) {
return callback(err);
}

async.eachSeries(paths, add, function(err) {
if(err) {
return callback(err);
}

var compressed = archive.generate({type: 'arraybuffer'});
fs.writeFile(zipfile, compressed, callback);
});
var compressed = jszip.generate({type: 'arraybuffer'});
var blob = new Blob([compressed], {type: "application/zip"});
saveAs(blob, "project.zip");
callback();
});
}

Expand Down Expand Up @@ -285,7 +261,7 @@ define(function (require, exports, module) {
untarWorker.postMessage({file: tarArchive.buffer});
}

exports.zip = zip;
exports.archive = archive;
exports.unzip = unzip;
exports.untar = untar;
});
2 changes: 2 additions & 0 deletions src/thirdparty/FileSaver.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit 6e12211

Please sign in to comment.