/* Create a project tree without any control files. Copyright (C) 2001, 2002 Tom Lord Copyright (C) 2002, 2003 Walter Landry and the Regents of the University of California Copyright (C) 2004, 2005 Walter Landry 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; version 2 dated June, 1991. 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, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "parse_common_options.hpp" #include "parse_unknown_options.hpp" #include "check_extra_args.hpp" #include "command_initializer.hpp" #include "arx_error.hpp" #include #include "boost/filesystem/operations.hpp" #include "boost/filesystem/fstream.hpp" #include "boost/filesystem/convenience.hpp" #include "get_revision.hpp" #include "Temp_Directory.hpp" #include #include "Current_Path.hpp" #include "Spawn.hpp" #include "config.h" #include "latest_tree_revision.hpp" #include "list_tree_branches.hpp" #include #include "output_changelog.hpp" #include "recursively_add_tags.hpp" #include "tempdir.hpp" using namespace std; using namespace boost; namespace fs=boost::filesystem; using fs::path; int export_cmd(list &argument_list, const command &cmd); static command_initializer export_init(command("export", "Create a project tree without ArX control files", "usage: export [options] [revision] [name] [dest-dir]", " --changelog include Changelogs in the tarball\n\ --tarball create a tarball, not a project tree\n\ --dir DIR cd to DIR first\n\ \n\ Create a new project tree without any ArX control files. With\n\ the --tarball option, ArX just creates a tarball (.tar.gz) of that\n\ project tree.\n\ \n\ If no revision is given, it uses the latest revision of the current tree.\n\ \n\ If no name is given, then the default name will be the branch name\n\ followed by the revision number. So for example\n\ \n\ arx export foo.bar.1.0,23 -> foo.bar.1.0.23/\n\ arx export foo.bar.1.0,23 baz -> baz/\n\ \n\ The tree or tarball will be placed in the current directory or DEST-DIR\n\ if specified. The destination is printed out.", export_cmd,"Miscellaneous Advanced",true)); int export_cmd(list &argument_list, const command &cmd) { Command_Info info(cmd); bool tarball(false), changelog(false); path target_dir(fs::current_path()); path tree_directory(fs::current_path()); while(!argument_list.empty()) if(!parse_common_options(argument_list,info)) { if(*(argument_list.begin())=="--dir") { argument_list.pop_front(); if(argument_list.empty()) { throw arx_error("Need an argument for --dir"); } tree_directory=path(*(argument_list.begin())); argument_list.pop_front(); } else if(*(argument_list.begin())=="--tarball") { tarball=true; argument_list.pop_front(); } else if(*(argument_list.begin())=="--changelog") { changelog=true; argument_list.pop_front(); } else { parse_unknown_options(argument_list); break; } } /* Get the branch to look at. */ Parsed_Name input_revision; string output_name; if(!argument_list.empty()) { input_revision=Parsed_Name(*(argument_list.begin())); argument_list.pop_front(); if(!argument_list.empty()) { output_name=*(argument_list.begin()); argument_list.pop_front(); if(!argument_list.empty()) { target_dir=fs::system_complete(*(argument_list.begin())); argument_list.pop_front(); } } } else { input_revision=latest_tree_revision(tree_directory); } check_extra_args(argument_list,info); /* Now get the revision. */ path parent; if(!output_name.empty()) parent=fs::system_complete(output_name).branch_path(); else parent=tempdir(); Temp_Directory export_dir(parent,",,export"); const Parsed_Name tag_name(get_revision(input_revision, export_dir.path/"revision", tree_directory).first); if(output_name.empty()) { output_name=input_revision.branch() + "." + tag_name.short_revision(); } list > tag_list; recursively_add_tags(tag_list,tag_name,export_dir.path/"revision"); /* Generate any changelogs and delete the _arx subdirectories */ for(list >::iterator i=tag_list.begin(); i!=tag_list.end(); ++i) { if(changelog) { const path changelog_dir(i->second/"Changelog.d"); if(lexists(changelog_dir)) { if(Command_Info::verbosity>=default_output) { cerr << "WARNING: Changelog directory " << changelog_dir.native_file_string() << " already exists." << endl << "Skipping this tree." << endl; } } else { list branch_list(list_tree_branches(i->second)); for(list::iterator j=branch_list.begin(); j!=branch_list.end(); ++j) { create_directories((changelog_dir/j->complete_branch()) .branch_path()); fs::ofstream changelog_file(changelog_dir /j->complete_branch()); output_changelog(i->second,*j,changelog_file); } } } remove_all(i->second/"_arx"); } if(!tarball) { fs::rename(export_dir.path/"revision",target_dir/output_name); cout << (target_dir/output_name).native_file_string() << endl; } else { { Current_Path temp(export_dir.path); fs::rename("revision",output_name); Spawn s; s << ARXTAR << "-zcf" << (output_name + ".tar.gz") << output_name; s.execute(true); } fs::rename(export_dir.path/(output_name + ".tar.gz"), target_dir/(output_name + ".tar.gz")); cout << (target_dir/(output_name + ".tar.gz")).native_file_string() << endl; } return 0; }