diff --git a/src/filesystem.cpp b/src/filesystem.cpp index 92244821..f56f3f51 100644 --- a/src/filesystem.cpp +++ b/src/filesystem.cpp @@ -189,17 +189,12 @@ bool FileSystem::makeTree(const QString &path) const return QDir().mkpath(path); } -bool FileSystem::remove(const QString &path) const -{ - return QFile::remove(path); -} - -bool FileSystem::removeDirectory(const QString &path) const +bool FileSystem::_removeDirectory(const QString &path) const { return QDir().rmdir(path); } -bool FileSystem::removeTree(const QString &path) const +bool FileSystem::_removeTree(const QString &path) const { QDir dir(path); bool res = false; @@ -207,16 +202,16 @@ bool FileSystem::removeTree(const QString &path) const if (dir.exists()) { foreach(QFileInfo info, dir.entryInfoList(QDir::NoDotAndDotDot | QDir::System | QDir::Hidden | QDir::AllDirs | QDir::Files, QDir::DirsFirst)) { if (info.isDir()) { - res = removeTree(info.absoluteFilePath()); + res = _removeTree(info.absoluteFilePath()); } else { - res = remove(info.absoluteFilePath()); + res = _remove(info.absoluteFilePath()); } if (!res) { return res; } } - res = removeDirectory(path); + res = _removeDirectory(path); } return res; @@ -303,3 +298,12 @@ QObject *FileSystem::_open(const QString &path, const QString &mode) const qDebug() << "FileSystem::open - " << "Couldn't be opened:" << path; return NULL; } + +bool FileSystem::_remove(const QString &path) const +{ + return QFile::remove(path); +} + +bool FileSystem::_copy(const QString &source, const QString &destination) const { + return QFile(source).copy(destination); +} diff --git a/src/filesystem.h b/src/filesystem.h index 5e8b0aa6..e14fe0ec 100644 --- a/src/filesystem.h +++ b/src/filesystem.h @@ -72,16 +72,10 @@ public: public slots: // Attributes - // 'size(path)' implemented in "bootstrap.js" JavaScript shim, using '_size(path)' + // 'size(path)' implemented in "fs-shim.js" using '_size(path)' int _size(const QString &path) const; QVariant lastModified(const QString &path) const; - // Files / Directories - // - copy() - // - move() - // - touch(path, date) - // - rename() - // Directory // - copyTree(source, target) //< copies files from a source path to a target path, // copying the files of the source tree to the corresponding locations @@ -89,16 +83,22 @@ public slots: // symbolic links to directories. bool makeDirectory(const QString &path) const; bool makeTree(const QString &path) const; - bool removeDirectory(const QString &path) const; - bool removeTree(const QString &path) const; + // 'removeDirectory(path)' implemented in "fs-shim.js" using '_removeDirectory(path)' + bool _removeDirectory(const QString &path) const; + // 'removeTree(path)' implemented in "fs-shim.js" using '_removeTree(path)' + bool _removeTree(const QString &path) const; // Files - // 'open(path, mode)' implemented in "bootstrap.js" JavaScript shim, using '_open(path, mode)' + // 'open(path, mode)' implemented in "fs-shim.js" using '_open(path, mode)' QObject *_open(const QString &path, const QString &mode) const; - // 'read(path)' implemented in "bootstrap.js" JavaScript shim - // 'write(path, mode)' implemented in the "bootstrap.js" JavaScript shim - - bool remove(const QString &path) const; + // 'read(path)' implemented in "fs-shim.js" + // 'write(path, mode)' implemented in the "fs-shim.js" + // 'remove(path)' implemented in "fs-shim.js" using '_remove(path)' + bool _remove(const QString &path) const; + // 'copy(source, destination)' implemented in "fs-shim.js" using '_copy(source, destination)' + bool _copy(const QString &source, const QString &destination) const; + // 'move(source, destination)' implemented in "fs-shim.js" + // 'touch(path)' implemented in "fs-shim.js" // Listing QStringList list(const QString &path) const; diff --git a/src/fs-shim.js b/src/fs-shim.js new file mode 100644 index 00000000..9215474a --- /dev/null +++ b/src/fs-shim.js @@ -0,0 +1,151 @@ +/*jslint sloppy: true, nomen: true */ +/*global window:true,phantom:true,fs:true */ + +/* + This file is part of the PhantomJS project from Ofi Labs. + + Copyright (C) 2011 Ivan De Marino + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of the nor the + names of its contributors may be used to endorse or promote products + derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +// window.fs +// JavaScript "shim" to throw exceptions in case a critical operation fails. + +/** Open and return a "file" object. + * It will throw exception if it fails. + * + * @param path Path of the file to open + * @param mode Open Mode. A string made of 'r', 'w', 'a/+' characters. + * @return "file" object + */ +window.fs.open = function (path, mode) { + var file = window.fs._open(path, mode); + if (file) { + return file; + } + throw "Unable to open file '" + path + "'"; +}; + +/** Open, read and return content of a file. + * It will throw an exception if it fails. + * + * @param path Path of the file to read from + * @return file content + */ +window.fs.read = function (path) { + var f = fs.open(path, 'r'), + content = f.read(); + + f.close(); + return content; +}; + +/** Open and write content to a file + * It will throw an exception if it fails. + * + * @param path Path of the file to read from + * @param content Content to write to the file + * @param mode Open Mode. A string made of 'w' or 'a / +' characters. + */ +window.fs.write = function (path, content, mode) { + var f = fs.open(path, mode); + + f.write(content); + f.close(); +}; + +/** Return the size of a file, in bytes. + * It will throw an exception if it fails. + * + * @param path Path of the file to read the size of + * @return File size in bytes + */ +window.fs.size = function (path) { + var size = fs._size(path); + if (size !== -1) { + return size; + } + throw "Unable to read file '" + path + "' size"; +}; + +/** Copy a file. + * It will throw an exception if it fails. + * + * @param source Path of the source file + * @param destination Path of the destination file + */ +window.fs.copy = function (source, destination) { + if (!fs._copy(source, destination)) { + throw "Unable to copy file '" + source + "' at '" + destination + "'"; + } +}; + +/** Move a file. + * It will throw an exception if it fails. + * + * @param source Path of the source file + * @param destination Path of the destination file + */ +window.fs.move = function (source, destination) { + fs.copy(source, destination); + fs.remove(source); +}; + +/** Removes a file. + * It will throw an exception if it fails. + * + * @param path Path of the file to remove + */ +window.fs.remove = function (path) { + if (!fs._remove(path)) { + throw "Unable to remove file '" + path + "'"; + } +}; + +/** Removes a directory. + * It will throw an exception if it fails. + * + * @param path Path of the directory to remove + */ +window.fs.removeDirectory = function (path) { + if (!fs._removeDirectory(path)) { + throw "Unable to remove directory '" + path + "'"; + } +}; + +/** Removes a directory tree. + * It will throw an exception if it fails. + * + * @param path Path of the directory tree to remove + */ +window.fs.removeTree = function (path) { + if (!fs._removeTree(path)) { + throw "Unable to remove directory tree '" + path + "'"; + } +}; + +window.fs.touch = function (path) { + fs.write(path, "", 'a'); +}; \ No newline at end of file diff --git a/src/phantom.cpp b/src/phantom.cpp index 8b3a6643..c747a193 100644 --- a/src/phantom.cpp +++ b/src/phantom.cpp @@ -107,21 +107,20 @@ Phantom::Phantom(QObject *parent) setLibraryPath(QFileInfo(m_config.scriptFile()).dir().absolutePath()); + // Add 'phantom' and 'fs' object to the global scope m_page->mainFrame()->addToJavaScriptWindowObject("phantom", this); m_page->mainFrame()->addToJavaScriptWindowObject("fs", &m_filesystem); - QFile file(":/bootstrap.js"); - if (!file.open(QFile::ReadOnly)) { - Terminal::instance()->cerr("Can not bootstrap!"); - exit(1); + // Load all the required JavaScript 'shims' + QString jsShims[2] = { + ":/webpage-shim.js", + ":/fs-shim.js" + }; + for (int i = 0, len = 2; i < len; ++i) { + QFile f(jsShims[i]); + f.open(QFile::ReadOnly); //< It's OK to assume this succeed. If it doesn't, we have a bigger problem. + m_page->mainFrame()->evaluateJavaScript(QString::fromUtf8(f.readAll())); } - QString bootstrapper = QString::fromUtf8(file.readAll()); - file.close(); - if (bootstrapper.isEmpty()) { - Terminal::instance()->cerr("Can not bootstrap!"); - exit(1); - } - m_page->mainFrame()->evaluateJavaScript(bootstrapper); } QStringList Phantom::args() const diff --git a/src/phantomjs.qrc b/src/phantomjs.qrc index 820461f7..9c8dd5d7 100644 --- a/src/phantomjs.qrc +++ b/src/phantomjs.qrc @@ -3,7 +3,8 @@ phantomjs-icon.png coffee-script.js usage.txt - bootstrap.js + webpage-shim.js + fs-shim.js configurator.js diff --git a/src/bootstrap.js b/src/webpage-shim.js similarity index 80% rename from src/bootstrap.js rename to src/webpage-shim.js index 9101a6f5..f54f8527 100644 --- a/src/bootstrap.js +++ b/src/webpage-shim.js @@ -179,63 +179,3 @@ window.WebPage = function (opts) { return page; }; - -// window.fs -// JavaScript "shim" to throw exceptions in case a critical operation fails. - -/** Open and return a "file" object. - * It will throw exception if it fails. - * - * @param path Path of the file to open - * @param mode Open Mode. A string made of 'r', 'w', 'a/+' characters. - * @return "file" object - */ -window.fs.open = function (path, mode) { - var file = window.fs._open(path, mode); - if (file) { - return file; - } - throw "Unable to open file '" + path + "'"; -}; - -/** Open, read and return content of a file. - * It will throw an exception if it fails. - * - * @param path Path of the file to read from - * @return file content - */ -window.fs.read = function (path) { - var f = fs.open(path, 'r'), - content = f.read(); - - f.close(); - return content; -}; - -/** Open and write content to a file - * It will throw an exception if it fails. - * - * @param path Path of the file to read from - * @param content Content to write to the file - * @param mode Open Mode. A string made of 'w' or 'a / +' characters. - */ -window.fs.write = function (path, content, mode) { - var f = fs.open(path, mode); - - f.write(content); - f.close(); -}; - -/** Return the size of a file, in bytes. - * It will throw an exception if it fails. - * - * @param path Path fo the file to read the size of - * @return File size in bytes - */ -window.fs.size = function (path) { - var size = fs._size(path); - if (size !== -1) { - return size; - } - throw "Unable to read file '" + path + "' size"; -}; diff --git a/test/fs-spec-01.js b/test/fs-spec-01.js index 1bc9bdb5..91af7bc2 100644 --- a/test/fs-spec-01.js +++ b/test/fs-spec-01.js @@ -1,5 +1,8 @@ describe("Basic Files API (read, write, remove, ...)", function() { var FILENAME = "temp-01.test", + FILENAME_COPY = FILENAME + ".copy", + FILENAME_MOVED = FILENAME + ".moved", + FILENAME_EMPTY = FILENAME + ".empty", ABSENT = "absent-01.test"; it("should be able to create and write a file", function() { @@ -13,6 +16,13 @@ describe("Basic Files API (read, write, remove, ...)", function() { } catch (e) { } expect(fs.exists(FILENAME)).toBeTruthy(); }); + + it("should be able to create (touch) an empty file", function() { + expect(fs.exists(FILENAME_EMPTY)).toBeFalsy(); + fs.touch(FILENAME_EMPTY); + expect(fs.exists(FILENAME_EMPTY)).toBeTruthy(); + expect(fs.size(FILENAME_EMPTY)).toEqual(0); + }); it("should be able to read content from a file", function() { var content = ""; @@ -25,15 +35,49 @@ describe("Basic Files API (read, write, remove, ...)", function() { expect(content).toEqual("hello\nworld\n"); }); - it("should be able to remove a file", function() { - expect(fs.exists(FILENAME)).toBeTruthy(); - expect(fs.remove(FILENAME)).toBeTruthy(); - expect(fs.exists(FILENAME)).toBeFalsy(); + it("should be able to copy a file", function() { + expect(fs.exists(FILENAME_COPY)).toBeFalsy(); + fs.copy(FILENAME, FILENAME_COPY); + expect(fs.exists(FILENAME_COPY)).toBeTruthy(); + expect(fs.read(FILENAME)).toEqual(fs.read(FILENAME_COPY)); + }); + + it("should be able to move a file", function() { + expect(fs.exists(FILENAME)).toBeTruthy(); + var contentBeforeMove = fs.read(FILENAME); + fs.move(FILENAME, FILENAME_MOVED); + expect(fs.exists(FILENAME)).toBeFalsy(); + expect(fs.exists(FILENAME_MOVED)).toBeTruthy(); + expect(fs.read(FILENAME_MOVED)).toEqual(contentBeforeMove); + }); + + it("should be able to remove a (moved) file", function() { + expect(fs.exists(FILENAME_MOVED)).toBeTruthy(); + fs.remove(FILENAME_MOVED); + expect(fs.exists(FILENAME_MOVED)).toBeFalsy(); + }); + + it("should be able to remove a (copied) file", function() { + expect(fs.exists(FILENAME_COPY)).toBeTruthy(); + fs.remove(FILENAME_COPY); + expect(fs.exists(FILENAME_COPY)).toBeFalsy(); }); + it("should be able to remove an empty file", function() { + expect(fs.exists(FILENAME_EMPTY)).toBeTruthy(); + fs.remove(FILENAME_EMPTY); + expect(fs.exists(FILENAME_EMPTY)).toBeFalsy(); + }); + it("should throw an exception when trying to open for read a non existing file", function(){ expect(function(){ fs.open(ABSENT, "r"); }).toThrow("Unable to open file '"+ ABSENT +"'"); }); + + it("should throw an exception when trying to copy a non existing file", function() { + expect(function(){ + fs.copy(ABSENT, FILENAME_COPY); + }).toThrow("Unable to copy file '" + ABSENT + "' at '" + FILENAME_COPY + "'"); + }); }); \ No newline at end of file diff --git a/test/fs-spec-02.js b/test/fs-spec-02.js index 58fe8b0f..32aed558 100644 --- a/test/fs-spec-02.js +++ b/test/fs-spec-02.js @@ -6,7 +6,7 @@ describe("Attributes Files API", function() { it("should throw an exception when trying to read the size of a non existing file", function(){ expect(function(){ - fs.size(ABSENT, "r"); + fs.size(ABSENT); }).toThrow("Unable to read file '"+ ABSENT +"' size"); }); @@ -41,6 +41,6 @@ describe("Attributes Files API", function() { }); it("should remove temporary file '"+ FILENAME +"'", function(){ - expect(fs.remove(FILENAME)).toBeTruthy(); + fs.remove(FILENAME); }); }); \ No newline at end of file diff --git a/test/fs-spec-03.js b/test/fs-spec-03.js index dce8f22a..f29378eb 100644 --- a/test/fs-spec-03.js +++ b/test/fs-spec-03.js @@ -20,6 +20,6 @@ describe("Paths Files API", function() { it("shoudl return to previous Current Working Directory and remove temporary directory", function() { expect(fs.changeWorkingDirectory(START_CWD)).toBeTruthy(); - expect(fs.removeTree(TEST_DIR)).toBeTruthy(); + fs.removeTree(TEST_DIR); }); }); \ No newline at end of file