Skip to content
Snippets Groups Projects
Commit f0578349 authored by Nick Draper's avatar Nick Draper
Browse files

Merge remote-tracking branch 'origin/feature/6176_upload_scripts'

parents 493751b2 ff78ebdf
No related merge requests found
......@@ -471,10 +471,7 @@ They will work as was expected for folders @ref folders-sec.
it it necessary that it identifies who was responsible for changing
the file.
@param description is an optional argument, because, as
explained at @ref script-description-sec it may be already inside the
file. But, if the description is given, it will be inserted to the local
file (if it is a script) or to the README file inside the folder.
@param email An string that identifies the email of the author.
@exception ScriptRepoException may be triggered for an attempt to publish an
......@@ -486,7 +483,7 @@ They will work as was expected for folders @ref folders-sec.
*/
virtual void upload(const std::string & file_path, const std::string & comment,
const std::string & author,
const std::string & description = std::string()) = 0;
const std::string & email) = 0;
/** Define the file patterns that will not be listed in listFiles.
This is important to force the ScriptRepository to not list hidden files,
......
......@@ -383,6 +383,7 @@ set ( PYTHONALG_DIRS "${MANTID_ROOT}/Framework/PythonAPI/PythonAlgorithms;${MANT
set ( PYTHONPLUGIN_DIRS "${MANTID_ROOT}/Framework/PythonAPI/PythonAlgorithms;${MANTID_ROOT}/Framework/PythonInterface/plugins" )
set ( DATADIRS ${MANTID_ROOT}/../../Test/AutoTestData;${MANTID_ROOT}/instrument )
set ( COLORMAPS_FOLDER ${MANTID_ROOT}/Installers/colormaps/ )
SET ( MANTIDPUBLISHER "http://upload.mantidproject.org/scriptrepository/payload/publish_debug" )
# Construct script paths.
set ( MANTID_SCRIPTS ${MANTID_ROOT}/scripts )
......@@ -456,6 +457,7 @@ set ( PLUGINS ${MANTID_ROOT}/plugins )
set ( PYTHONALG_DIRS ${PLUGINS}/PythonAlgs ) # deprecated
set ( PYTHONPLUGIN_DIRS ${PLUGINS}/python )
set ( DATADIRS "" )
SET ( MANTIDPUBLISHER "http://upload.mantidproject.org/scriptrepository/payload/publish" )
# Construct script paths by replacing the old MANTID_ROOT with the new one.
# Unfortunately string (REGEX REPLACE ... )removes the semi-colons so we have to do this in a loop.
......
......@@ -200,8 +200,8 @@ algorithms.categories.hidden=Workflow\\Inelastic\\UsesPropertyManager;Workflow\\
# ScriptRepository Properties:
# Url for the WebServer that support the upload of the files that the users want to share (not in usage)
UploaderWebServer =
# Url for the WebServer that support the upload of the files that the users want to share
UploaderWebServer = @MANTIDPUBLISHER@
# Local system path for the script repository.
ScriptLocalRepository =
# Url for the remote script repository.
......
......@@ -99,7 +99,7 @@ namespace API{
void upload(const std::string & file_path, const std::string & comment,
const std::string & author,
const std::string & description = std::string());
const std::string & email);
/* Return true if there is a local repository installed*/
bool isValid(void);
......@@ -135,6 +135,8 @@ namespace API{
std::string local_repository;
/// URL for the remote repository, usually:
std::string remote_url;
/// URL for the upload
std::string remote_upload;
private:
......
......@@ -18,6 +18,9 @@ using Mantid::Kernel::ConfigServiceImpl;
#include <Poco/Exception.h>
#include <Poco/Net/HTTPResponse.h>
#include <Poco/Net/NetException.h>
#include <Poco/Net/HTMLForm.h>
#include "Poco/Net/FilePartSource.h"
// Visual Studion compains with the inclusion of Poco/FileStream
// disabling this warning.
......@@ -51,10 +54,6 @@ namespace Mantid
namespace API
{
static void notImplemented(){
throw ScriptRepoException("This method is not implemented yet");
};
static ScriptRepoException pocoException(const std::string & info,
Poco::Exception & ex){
std::stringstream ss;
......@@ -110,10 +109,11 @@ namespace API
{
// get the local path and the remote path
std::string loc, rem;
ConfigServiceImpl & config = ConfigService::Instance();
remote_upload = config.getString("UploaderWebServer");
if (local_rep.empty() || remote.empty()){
ConfigServiceImpl & config = ConfigService::Instance();
loc = config.getString("ScriptLocalRepository");
rem = config.getString("ScriptRepository");
rem = config.getString("ScriptRepository");
}else{
local_repository = local_rep;
remote_url = remote;
......@@ -440,7 +440,7 @@ namespace API
st |= LOC;
// the file is remote_changed if the date of the pub_date file is
// diferent from the local downloaded pubdate.
if (entry.pub_date != entry.downloaded_pubdate)
if (entry.pub_date > entry.downloaded_pubdate)
st |= REMO;
......@@ -691,20 +691,131 @@ namespace API
}
/**
@todo Describe
* Uploads one file to the ScriptRepository web server, pushing, indirectly, to the
* git repository. It will send in a POST method, the file and the following fields:
* - author : Will identify the author of the change
* - email: Will identify the email of the author
* - comment: Description of the nature of the file or of the update
*
* It will them upload to the URL pointed to UploaderWebServer. It will them receive a json file
* with some usefull information about the success or failure of the attempt to upload.
* In failure, it will be converted to an appropriated ScriptRepoException.
*/
void ScriptRepositoryImpl::upload(const std::string & file_path,
const std::string & comment,
const std::string & author,
const std::string & description)
const std::string & email)
{
UNUSED_ARG(file_path);
UNUSED_ARG(comment);
UNUSED_ARG(author);
UNUSED_ARG(description);
notImplemented();
using namespace Poco::Net;
try{
g_log.notice() << "ScriptRepository uploading " << file_path << " ..." << std::endl;
Poco::URI uri(remote_upload);
std::string path(uri.getPathAndQuery());
HTTPClientSession session(uri.getHost(), uri.getPort());
HTTPRequest req(HTTPRequest::HTTP_POST, path,
HTTPMessage::HTTP_1_0);
HTMLForm form(HTMLForm::ENCODING_MULTIPART);
// add the fields author, email and comment
form.add("author",author);
form.add("mail", email);
form.add("comment",comment);
// deal with the folder
std::string relative_path = convertPath(file_path);
std::string absolute_path = local_repository + relative_path;
std::string folder = "./";
size_t pos = relative_path.rfind('/');
if (pos != std::string::npos)
folder += std::string(relative_path.begin(), relative_path.begin() + pos);
if (folder[folder.size()-1] != '/')
folder += "/";
g_log.information() << "Uploading to folder: " << folder << std::endl;
form.add("path",folder);
// inserting the file
FilePartSource * m_file = new FilePartSource(absolute_path);
form.addPart("file",m_file);
form.prepareSubmit(req);
// get the size of everything
std::stringstream sst;
form.write(sst);
// move back to the begining of the file
m_file->stream().clear();
m_file->stream().seekg(0,std::ios::beg);
// set the size
req.setContentLength((int)sst.str().size());
std::ostream& ostr = session.sendRequest(req);
// send the request.
ostr << sst.str();
HTTPResponse response;
std::istream & rs = session.receiveResponse(response);
g_log.information() << "ScriptRepository upload status: "
<< response.getStatus() << " " << response.getReason() << std::endl;
std::stringstream answer;
{ // remove the status message from the end of the reply, in order not to get exception from the read_json parser
std::stringstream server_reply;
std::string server_reply_str;
Poco::StreamCopier::copyStream(rs, server_reply);
server_reply_str= server_reply.str();
size_t pos = server_reply_str.rfind("}");
if (pos != std::string::npos)
answer << std::string(server_reply_str.begin() , server_reply_str.begin() + pos + 1);
else
answer << server_reply_str;
}
g_log.debug() << "Form Output: " << answer.str() << std::endl;
std::string info;
std::string detail;
std::string published_date;
ptree pt;
try{
read_json(answer, pt);
info = pt.get<std::string>("message","");
detail = pt.get<std::string>("detail","");
published_date = pt.get<std::string>("pub_date","");
std::string cmd = pt.get<std::string>("shell","");
if (!cmd.empty())
detail.append("\nFrom Command: ").append(cmd);
}catch (boost::property_tree::json_parser_error & ex){
throw ScriptRepoException("Bad answer from the Server",
ex.what());
}
if (info == "success"){
g_log.notice() << "ScriptRepository:" << file_path << " uploaded!"<< std::endl;
// update the file
RepositoryEntry & entry = repo.at(file_path);
{
Poco::File local(absolute_path);
entry.downloaded_date = DateAndTime(Poco::DateTimeFormatter::format(local.getLastModified(),
timeformat));
// update the pub_date and downloaded_pubdate with the pub_date given by the upload.
// this ensures that the status will be correctly defined.
if (!published_date.empty())
entry.pub_date = DateAndTime(published_date);
entry.downloaded_pubdate = entry.pub_date;
entry.status = BOTH_UNCHANGED;
}
g_log.information() << "ScriptRepository update local json " << std::endl;
updateLocalJson(file_path, entry); ///FIXME: performance!
}else
throw ScriptRepoException(info, detail);
}catch(Poco::Exception & ex){
throw ScriptRepoException(ex.displayText(), ex.className());
}
}
/** The ScriptRepositoryImpl is set to be valid when the local repository path
......@@ -853,6 +964,7 @@ namespace API
//Configure Poco HTTP Client Session
try{
Poco::Net::HTTPClientSession session(uri.getHost(), uri.getPort());
session.setTimeout(Poco::Timespan(2,0));// 2 secconds
Poco::Net::HTTPRequest request(Poco::Net::HTTPRequest::HTTP_GET, path,
Poco::Net::HTTPMessage::HTTP_1_1);
Poco::Net::HTTPResponse response;
......@@ -1054,8 +1166,12 @@ namespace API
// array.push_back(std::make_pair("auto_update",entry.auto_update)));
local_json.push_back( std::pair<std::string, boost::property_tree::basic_ptree<std::string,std::string> >(path,array) );
}else{
local_json.put(std::string(path).append(".downloaded_pubdate"),
entry.downloaded_pubdate.toFormattedString());
local_json.put(
boost::property_tree::ptree::path_type( std::string(path).append("!downloaded_pubdate"), '!'),
entry.downloaded_pubdate.toFormattedString().c_str());
local_json.put(
boost::property_tree::ptree::path_type( std::string(path).append("!downloaded_date"), '!'),
entry.downloaded_date.toFormattedString().c_str());
}
//g_log.debug() << "Update LOCAL JSON FILE" << std::endl;
#if defined(_WIN32) || defined(_WIN64)
......
......@@ -315,6 +315,13 @@ bool RepoModel::setData(const QModelIndex & index, const QVariant & value,
}
}else if (action == "Upload"){
QWidget * father = qobject_cast<QWidget*>(QObject::parent());
if (repo_ptr->fileInfo(path).directory){
QMessageBox::information(father,
"Not Supported",
"The current version does not support uploading recursively. Please, upload one-by-one");
return false;
};
UploadForm * form = new UploadForm(QString::fromStdString(path), father);
QSettings settings;
settings.beginGroup("Mantid/ScriptRepository");
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment