//
// aegis - project change supervisor
// Copyright (C) 1992-1999, 2001-2008, 2011-2014 Peter Miller
// Copyright (C) 2007, 2008 Walter Franzini
//
// 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; either version 3 of the License, or (at
// your option) any later version.
//
// 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, see .
//
#ifndef PROJECT_H
#define PROJECT_H
#include
#include
#include
#include
#include
class string_list_ty; // forward
class sub_context_ty; // forward
class fstate_src_ty; // forward
class itab_ty; // forward
/**
* The project class is used to remember the state of a project.
*
* Eventually, it will be discouraged to use this class directly. The
* preferred method will be to access it via a project class (see
* below) smart pointer. This will be able to guarantee the reference
* counting semantics.
*
* This class is presently in transition from being a C struct. One by
* one the access functions will be turned into access methids, and the
* instance variables will become private.
*/
class project
{
public:
/**
* The pointer typedef is provided so that clients of this
* interface may use change::pointer everywhere they need to point
* at a change instance, and only this typedef needs to be edited
* to use a variety of smart pointer instead.
*/
typedef project *pointer;
private:
/**
* The destructor.
*
* It is not virtual; thou shalt not derive fron this class.
*
* @note
* This method is private, to ensure the reference counting
* always works. The correct way to release a reference is to
* call the #project::free method.
*/
~project();
public:
/**
* The constructor.
*
* @param name
* The name of the project.
*/
project(string_ty *name);
// NOTE: methods are sorted alphabetically. To have methods
// grouped, make sure they change their suffix rather than their
// prefix. E.g. thingumy_get and thingumy_set rather than
// get_thingumy and set_thingumy.
//
// Note: public or protected or private, it doesn't matter, keep
// them sorted.
// ---------- A ------------------------------------------------------
/**
* The attribute_get method is used to obtain the value of an
* attribute of this project.
*
* The project attributes are kept in the project_specific
* field of the project config file (aegis.conf) which is
* a project source file. Only use this method when you want the
* baseline attributes, use change::pconf_attributes_find
* within a change set.
*
* @param name
* The name of the attribute.
* Attribute names are not case sensitive.
* @returns
* the string value of the attribute, or the empty string
* if not found.
*/
nstring attribute_get(const nstring &name);
/**
* The attribute_get_boolean method is used to obtain the value of
* an attribute of this project, as a true/false value.
*
* The project attributes are kept in the project_specific
* field of the project config file (aegis.conf)
* which is a project source file. Only use this method
* when you want the baseline attributes, use
* change::pconf_attributes_find_boolean within a change set.
*
* @param name
* The name of the attribute.
* Attribute names are not case sensitive.
* @returns
* the boolean value of the attribute, or false if the
* attribute is not found or is not interpretable as a
* boolean.
*/
bool attribute_get_boolean(const nstring &name);
// ---------- B ------------------------------------------------------
/**
* The baseline_path_get method is used to obtain the absolure path
* of the project's (branch's) baseline.
*
* @param resolve
* Whether or not to resolve all of the symlinks in the path.
*/
string_ty *baseline_path_get(bool resolve = false);
/**
* The bind_branch method is used to bind a branch of this project
* into a new project object.
*
* @param bp
* The change corresponding to the project of interest.
*/
project *bind_branch(const change::pointer &bp);
/**
* The bind_existing method is used to bind a newly created project
* object to an existing project.
*
* @note
* This method does not return if there is an error. A fatal
* error message will be produced in this case.
*/
void bind_existing();
/**
* The bind_existing_errok method is used to bind a newly created
* project object to an existing project.
*
* @returns
* bool; true if bound successfully, false if not
*/
bool bind_existing_errok();
/**
* The bind_keep method is used to bind a new project to an
* existing directory, as needed by the "aenpr -keep" option.
*
* @param path
* The directory containing the project.
*/
void bind_keep(const nstring &path);
/**
* The bind_new method is used to bind a new project object to a
* new name. This will create all of the necessary data structures
* and (eventually) files, once the project directory has been set.
*/
void bind_new();
// ---------- C ------------------------------------------------------
/**
* The change_completion_timestamp is used to
* determine the completion timestamp of a change.
*
* @param change_number
* the number of the change.
*
* @returns
* the completion timestamp of the change.
*
* @note
* this method caches its results for speed.
*/
time_t change_completion_timestamp(long change_number);
/**
* The change_get method is used to obtain a pointer to the change
* object representing this project branch.
*
* @returns
* pointer to change object;
*/
change::pointer change_get(void);
/**
* The change_get_raw method is used to obtain a pointer to the change
* object representing this project branch or NULL if no such object
* is in the project.
*
* @returns
* pointer to change object;
* DO NOT change_free() or delete it.
*/
change::pointer change_get_raw() { return pcp; }
/**
* The change_path_get method is used to obtain the absolute path
* of the meta-data of a specific change set.
*
* @param change_number
* The number of the change for which the path is desired.
* @returns
* a string; use str_free when you are done with.
*/
nstring change_path_get(long change_number);
void
change_reset(void)
{
pcp.reset();
}
/**
* The changes_path_get method is used to obtain the absolute path
* of the directory containing change set meta-data.
*
* @returns
* a string; do not str_free or delete it, because it is cached.
*/
string_ty *changes_path_get();
public: // during transition, then private
/**
* The convert_to_new_format method is used to convert Aegis 2.3
* project meta-data into Aegis 3.0 (and later) project meta-data.
*/
void convert_to_new_format();
public:
/**
* The copy_the_owner method is used to copy the owner from another
* project. It is only ever used by aenrls, which sort-of clones
* another project. Don't use this method.
*
* Note: this is only a transient requirement for new projects.
* Existing projects take their uid and gid from the Unix uid and
* gid of the project directory.
*/
void copy_the_owner(project *pp);
/**
* The copy method is to make a copy of the project object,
* it is a reference counted shallow copy.
*/
project *copy(void);
/**
* the copyright_years_slurp method is used to determine the range
* of copyright years covered by this project and all its ancrestor
* projects back to the trunk.
*
* @param a
* The array to store the results in
* @param amax
* The maximum number of distinct years which can be stored in
* the array (see SIZEOF macro).
* @param alen_p
* This is a pointer to the array length used to date.
*/
void copyright_years_slurp(int *a, int amax, int *alen_p);
// ---------- D ------------------------------------------------------
// ---------- E ------------------------------------------------------
// ---------- F ------------------------------------------------------
/**
* The file_directory_query method is used to determine whether or
* not a given file name is actually a directory name, and if it
* is, expand it into a list of files below that directory.
*
* @param filename
* The name of the file to be checked.
* @param result_in
* If the filename is a directory, will be filled with a list
* of files existing in that directory.
* @param result_out
* If the filename is a directory, will be filled with a list
* of removed files from that directory.
* @param as_view_path
* The view path style to be used.
*/
bool file_directory_query(const nstring &filename, nstring_list &result_in,
nstring_list &result_out, view_path_ty as_view_path);
/**
* The file_directory_query method is used to determine whether or
* not a given file name is actually a directory name, and if it
* is, expand it into a list of files below that directory.
*
* @param filename
* The name of the file to be checked.
* @param result_in
* If not NULL, and if the filename is a directory, will be
* filled with a list of files existing in that directory.
* @param result_out
* If not NULL, and if the filename is a directory, will be
* filled with a list of removed files from that directory.
* @param as_view_path
* The view path style to be used.
*/
void file_directory_query(string_ty *filename,
struct string_list_ty *result_in, struct string_list_ty *result_out,
view_path_ty as_view_path);
/**
* The file_exists method is used to determine whether or not a
* file exists in the project baseline, or any of the ancestor
* basleines.
*
* @param filename
* The base-relative name of the file to search for.
*/
bool file_exists(const nstring &filename);
/**
* The free method is used to release a reference to the project.
* It takes care of the reference counting.
*/
void free(void);
/**
* The file_find method is used to find the state information of
* the named file within the project. It will search the immediate
* branch, and then any ancestor branches until the file is found.
*
* @param filename
* The base-relative name of the file to search for.
* @param as_view_path
* If this is true, apply viewpath rules to the file (i.e. if
* it is removed, return a null pointer) if false return first
* instance found.
*/
fstate_src_ty *file_find(const nstring &filename,
view_path_ty as_view_path);
/**
* The file_find method is used to find the state information of
* the named file within the project. It will search the immediate
* branch, and then any ancestor branches until the file is found.
*
* @param filename
* The base-relative name of the file to search for.
* @param as_view_path
* If this is true, apply viewpath rules to the file (i.e. if
* it is removed, return a null pointer) if false return first
* instance found.
*/
fstate_src_ty *file_find(string_ty *filename, view_path_ty as_view_path);
/**
* The file_find method is used to find the state information of a
* file within the project, given the corresponding change file's
* meta-data. It will search the immediate branch, and then any
* ancestor branches until the file is found.
*
* @param c_src
* The change file meta-data for which the corresponding project
* file is sought.
* @param as_view_path
* If this is true, apply viewpath rules to the file (i.e. if
* it is removed, return a null pointer) if false return first
* instance found.
*/
fstate_src_ty *file_find(fstate_src_ty *c_src, view_path_ty as_view_path);
/**
* The file_find method is used to find the state information of a
* file within the project, given the corresponding change file's
* meta-data. It will search the immediate branch, and then any
* ancestor branches until the file is found.
*
* @param c_src
* The change file meta-data for which the corresponding project
* file is sought.
* @param as_view_path
* If this is true, apply viewpath rules to the file (i.e. if
* it is removed, return a null pointer) if false return first
* instance found.
*/
fstate_src_ty *file_find(cstate_src_ty *c_src, view_path_ty as_view_path);
/**
* The file_find_by_uuid method is used to find the state
* information of a file within the project, given the file's UUID.
* It will search the immediate branch, and then any ancestor
* branches until the file is found.
*
* \param uuid
* The UUID of the file to search for.
* \param vp
* If this is true, apply viewpath rules to the file (i.e. if
* it is removed, return a null pointer) if false return first
* instance found.
*/
fstate_src_ty *file_find_by_uuid(string_ty *uuid, view_path_ty vp);
/**
* The file_find_fuzzy method is used to find the state information
* for a project file when the project::file_find function fails.
* It uses fuzzy string matching, which is significantly slower
* than exact searching, but can provide very useful error messages
* for users.
*
* \param filename
* The base-relative name of the file to search for.
* \param as_view_path
* If this is true, apply viewpath rules to the file (i.e. if
* it is removed, return a null pointer) if false return first
* instance found.
*/
fstate_src_ty *file_find_fuzzy(string_ty *filename,
view_path_ty as_view_path);
private:
/**
* The file_list_get method is used to obtain a list of file names.
* The lists are calculated on demand and cached.
*
* \param as_view_path
* The view path style to use when calculating the list of
* project files.
* \returns
* Pointer to a string list, do not delete it, it is cached.
*/
struct string_list_ty *file_list_get(view_path_ty as_view_path);
public:
/**
* The file_list_invalidate method is used to clear the cahced
* project file information when it becomes stale.
*/
void file_list_invalidate();
/**
* The file_new method is used to create a new project file by
* name, and add it to the project file manifest. No validation is
* done, the called must guarantee that the file name is unique.
*
* \param file_name
* The base-relative name of the file to search for.
*/
fstate_src_ty *file_new(string_ty *file_name);
/**
* The file_new method is used to create a new project file from
* the meta data of an existing (usually change set) file, and add
* it to the project file manifest. No validation is done, the
* caller must guarantee that the file name and UUID are unique.
*
* \param meta
* The meta data, including the name and UUID, of the file to
* be created.
*/
fstate_src_ty *file_new(fstate_src_ty *meta);
/**
* The file_nth method is used to get the 'n'th file from the list
* of project files.
*
* \param n
* The file number to obtain (zero based).
* \param as_view_path
* The style of view path to use when calculating the list.
* \returns
* pointer to file mete-data, or NULL if beyond end of list
*/
fstate_src_ty *file_nth(size_t n, view_path_ty as_view_path);
/**
* The file_version_path method is used to obtain a file path that
* contains the source of the file referenced by the given meta-data.
*
* @param src
* Meta data of the file in question. Contains uuid and version info.
* @param unlink_flag
* This is set to true on return for files that need to be
* unlinked when done with (i.e. historical versions).
*/
string_ty *file_version_path(fstate_src_ty *src, bool &unlink_flag);
/**
* The find_branch method is used to locate the branch with the
* given number in this project.
*
* @param number
* The branch number to locate.
* @returns
* Pointer to valid project object.
*/
project *find_branch(const char *number);
// ---------- G ------------------------------------------------------
private:
/**
* The get_the_owner method is used to determine the Unix pid and
* gid for the project.
*/
void get_the_owner();
public:
/**
* The get_user method may be used to obtain a pointer to the user
* (and group) ownership date for this project.
*/
user_ty::pointer get_user() const;
/**
* The gid_get method is used to obtain the Unix group id of the
* project owner.
*/
int gid_get();
// ---------- H ------------------------------------------------------
/**
* The history_path_get method is used to determine the top-level
* directory of the tree which is used to hold the project's
* history files.
*
* @returns
* a pointer to a string. Do NOT free this string when you are
* done with it, because it is cached.
*/
string_ty *history_path_get();
/**
* The home_path_get method is used to get the "home" directory
* of a project; the directory which contains trunk's delta
* directories and the baseline, and the "info" meta-data
* directory.
*
* @returns
* a string containing the absolute path.
* DO NOT str_free or delete it.
*
* @note
* It is a bug to call this method for anything other than a
* trunk project. Calling if for a branch will result in an
* assert failure.
*/
string_ty *home_path_get();
/**
* The home_path_set method is used when creating a new project to
* remeber the directory the project beaselines and meta-data are
* stored within.
*
* @param dir
* The absolute path of the directory in which to keep the
* project. To cope with automounters, directories are stored
* as given, or are derived from the home directory in the
* passwd file. Within Aegis, pathnames have their symbolic
* links resolved, and any comparison of paths is done on this
* "system idea" of the pathname.
*/
void home_path_set(string_ty *dir);
void home_path_set(const nstring &dir);
// ---------- I ------------------------------------------------------
/**
* The info_path_get method is used to obtain the absolute path of
* the meta-data file for this project (branch).
*
* @returns
* a string; do not str_free or delete it, because it is cached.
* @note
* it is a bug to call this for anything but a top-level
* (trunk) project.
*/
string_ty *info_path_get();
/**
* The is_a_trunk method is used to determine whether a project
* is a trunk branch (is the deepest ancestor) or a normal nested
* branch (has at least one ancestor branch).
*
* @returns
* bool; true if is a trunk, false if is a branch
*/
bool is_a_trunk() const { return (parent == 0); }
// ---------- J ------------------------------------------------------
// ---------- K ------------------------------------------------------
// ---------- L ------------------------------------------------------
/**
* The list_inner method is used to append the branch names to the
* result list. This is one step of building a complete list of
* projects.
*
* @param result
* Append all project branch names to this list.
*/
void list_inner(string_list_ty &result);
/**
* The lock_prepare_everything method is used to take a resd-only
* lock of everything in the project: pstate, baseline, changes,
* and recurse into all active branches.
*/
void lock_prepare_everything();
private:
/**
* The lock_sync method is used to invalidate the project state
* data if the lock has been released and taken again.
*
* @note
* it is a bug to call this for anything but a top-level
* (trunk) project.
*/
void lock_sync();
// ---------- M ------------------------------------------------------
// ---------- N ------------------------------------------------------
public:
/**
* The name_get method is used to get the name of the project.
*
* @returns
* a string; the name of the project.
* DO NOT str_free it.
*/
string_ty *name_get() const;
// ---------- O ------------------------------------------------------
// ---------- P ------------------------------------------------------
/**
* The parent_branch_number_get method is used to get the branch
* (change) number of this branch in the parent branch.
*
* @note
* This method is not meaningful for trunk projects (branches).
*/
long parent_branch_number_get() const { return parent_bn; }
/**
* The parent_get method is used to obtain the parent brach of this
* project.
*
* @returns
* pointer to project; do not delete or project::free
*/
project *parent_get() { return (parent ? parent : this); }
/**
* The pstate_get method is used to obtain the project state data.
*
* @returns
* pointer to pstate_ty data; do not delete, it is cached.
* @note
* it is a bug to call this for anything but a top-level
* (trunk) project.
*/
pstate_ty *pstate_get();
/**
* The pstate_lock_prepare method is used to prepare to take a
* project pstate lock for this project, prior to lock_take() being
* called.
*/
void pstate_lock_prepare();
/**
* The pstate_path_get method is used to obtain the absolute path
* of the pstate (project state) file.
*
* @returns
* a string; do not str_free or delete it, because it is cached.
* @note
* it is a bug to call this for anything but a top-level
* (trunk) project.
*/
string_ty *pstate_path_get();
/**
* The search_path_get method may be used to obtain the search path
* (list of progressively more out-of-date ancestor btranches)
* within which to search for files.
*
* @param result
* Where to append the additional directories.
* @param resolve
* Whether or not to expand synbolic links within paths.
*/
void search_path_get(string_list_ty *result, bool resolve);
/**
* The search_path_get method may be used to obtain the search path
* (list of progressively more out-of-date ancestor btranches)
* within which to search for files.
*
* @param result
* Where to append the additional directories.
* @param resolve
* Whether or not to expand synbolic links within paths.
*/
void search_path_get(nstring_list &result, bool resolve);
/**
* The pstate_write method is used to write out the project state
* data into the meta-data directory tree.
*/
void pstate_write();
// ---------- Q ------------------------------------------------------
// ---------- R ------------------------------------------------------
// ---------- S ------------------------------------------------------
// ---------- T ------------------------------------------------------
/**
* The trunk_get method is used to find the trunk project of this
* project, then top-level branch of this project.
*/
project *trunk_get();
/**
* The top_path_get method is used to obtain the absolute path of
* the projet direvtory, the one above "baseline".
*
* @param resolve
* Whether or not to expand synbolic links within paths.
*/
nstring top_path_get(bool resolve);
// ---------- U ------------------------------------------------------
// ---------- V ------------------------------------------------------
// ---------- W ------------------------------------------------------
// ---------- X ------------------------------------------------------
// ---------- Y ------------------------------------------------------
// ---------- Z ------------------------------------------------------
// ---------------------------------------------------------------------
/**
* The uid_get method is used to obtain the Unix user id of the
* project owner.
*/
int uid_get();
/**
* The umask_get method is used to obtain the file creation mode
* mask for this project.
*/
int umask_get();
private:
/**
* The reference_count instance variable isd used to remember the
* numer of references to this data struvture have been registered.
*/
long reference_count;
/**
* The name instance variable is used to remember the name of this
* project.
*/
string_ty *name;
/**
* The home_path instance variable is used to remember the "home"
* directory of a project; the directory which contains trunk's
* delta directories and the baseline, and the "info" meta-data
* directory.
*
* @note
* Never access this instance variable directly, always go via
* home_path_get() in case it hasn't been calculated yet.
*/
string_ty *home_path;
/**
* The baseline_path_unresolved instance variable is used to
* remember the absolute path of this project's (branch's) baseline
* directory. It has not had is symbolic links resolved. All
* access is via the baseline_path_get method, which takes care of
* calculating it on demand.
*/
string_ty *baseline_path_unresolved;
/**
* The baseline_path_unresolved instance variable is used to
* remember the absolute path of this project's (branch's) baseline
* directory. It has not had is symbolic links resolved. All
* access is via the baseline_path_get method, which takes care of
* calculating it on demand.
*/
string_ty *baseline_path;
/**
* The change2time_stp instance variable is used to remember for
* each change the completion timestamp. All access are via the
* change_completion_timestamp_maybe_cached method, which take
* care of calculating it on demand.
*/
itab_ty *change2time_stp;
/**
* The history_path is used to remember the absolute path of the
* distory directory. The calculation is deferred until needed.
* Always use the history_path_get method, never access this
* instance variable directly.
*/
string_ty *history_path;
/**
* The info_path instance variable is used to remember the location
* of the meta-data file for this project (branch). Never access
* the info_path variable directly, always go via the info_path_get
* method.
*/
string_ty *info_path;
/**
* The pstate_path instance variable is used to remember the
* absolute path of the pstate (project state) file. It is
* calculated as needed. Never access this instance variable
* directly, always go via the pstate_path_get method.
*/
string_ty *pstate_path;
/**
* The changes_path instance variable is used to remember the
* absolute path of the directory containing change set meta-data.
* It is calculated as needed. Never access this instance variable
* directly, always go via the changes_path_get method.
*/
string_ty *changes_path;
/**
* The pstate_data instance variable is used to remember the
* project state data. It is calculated as needed. Never
* access this instance variable directly, always go via the
* pstate_get method.
*/
pstate_ty *pstate_data;
/**
* The is_a_new_file instance variable is used to remember whether
* the pstate file is a new file which has to be created.
*/
bool is_a_new_file;
/**
* The lock_magic instance variable is used to remember the last
* time the lock was taken. If the lock_sync function returns
* different, it means we have to invalidate all our project data
* and read it in again, because something could have changed.
* Only every accessed by the lock_sync ethod.
*/
long lock_magic;
/**
* The pcp instance variable is used to remember the change object
* representing this branch's state.
*
* @note
* Never access this instance variable directly, event from a
* project method, always go via the change_get() method in
* case it has not been calculated yet.
*/
change::pointer pcp;
/**
* The uid instance variable is used to remember the Unix user id
* for the project owner. This is set by the get_the_owner method.
*/
int uid;
/**
* The gid instance variable is used to remember the Unix group id
* for the project owner. This is set by the get_the_owner method.
*/
int gid;
/**
* The parent instance variable is used to remember the project
* which this project is a branch of. If it is NULL, then this is
* a trunk project.
*/
project *parent;
/**
* The parent_bn instance variable is used to remember the change
* (branch) number of this project relative to the parent branch.
* If it is TRUNK_BRANCH_NUMER, then this is a trunk project.
*/
long parent_bn;
/**
* The file_list instance variable is used to remember the list
* of files in the project, one list for each style of view path.
* Never access this instance variable directly, always go via the
* file_list_get method, they are calculated on demand.
*/
struct string_list_ty *file_list[view_path_MAX];
/**
* The file_by_uuid instance variable is used to remember a symbol
* table of files indexed by UUID (or by file name if your project
* has any files without a UUID for backwards compatibility).
*
* This instance variable shall always be accessed via the
* find_file_by_uuid method. The tables are calculated on demand
* and cached.
*/
struct symtab_ty *file_by_uuid[view_path_MAX];
//
// If you add an instance variable to this class, make sure you
// dispose of it in the destructor and initialize in in the
// constructor. Both may be found in libaegis/project.cc
//
private:
/**
* The up instance variable is used to remember the user (and
* group) which owns this project.
*/
user_ty::pointer up;
/**
* The off_limits instance variable is used to remember when
* a project is inaccessable to the executing user. This
* flag is normally false, but it will be set to true by
* project::bind_existing for projects which are inaccessable.
*/
bool off_limits;
/**
* The default constructor.
*
* Do not use this method. It is not defined. Projects will
* always have a name, it it shall always be supplied to the
* constructor.
*/
project();
/**
* The copy constructor. Do not use.
*
* The prefereed mechanism is to use the reference counting
* provided the the project class (see below) smart pointer.
*/
project(const project &);
/**
* The assignment operator. Do not use.
*
* The prefereed mechanism is to use the reference counting
* provided the the project class (see below) smart pointer.
*/
project &operator=(const project &);
};
project *project_alloc(string_ty *name);
void project_list_get(struct string_list_ty *);
inline nstring
project_name_get(project *pp)
{
return nstring(pp->name_get());
}
project *project_copy(project *);
string_ty *project_Home_path_get(project *);
/**
* The project_rss_path_get function is used to get the path of the RSS
* directory for the given project.
*
* @param pp
* The project in question
* @param resolve
* Whether or not to resolve symlinks in the path.
* @returns
* a string containing the absolute path
*/
nstring project_rss_path_get(project *pp, bool resolve = false);
/**
* The project_history_filename_get function is used to determine the
* absolute path pf the file used to contain the history of the given file.
*
* @returns
* a pointer to a string. You are required to str_free this string
* when you are done with it.
*/
string_ty *project_history_filename_get(project *, struct fstate_src_ty *);
void project_pstate_write_top(project *);
void project_pstate_lock_prepare_top(project *);
void project_baseline_read_lock_prepare(project *);
void project_baseline_write_lock_prepare(project *);
void project_history_lock_prepare(project *);
void project_error(project *, struct sub_context_ty *, const char *);
void project_fatal(project *, struct sub_context_ty *, const char *)
NORETURN;
void project_verbose(project *, struct sub_context_ty *, const char *);
void project_change_append(project *, long, int);
void project_change_delete(project *, long);
int project_change_number_in_use(project *, long);
nstring project_version_short_get(project *);
nstring project_version_get(project *);
user_ty::pointer project_user(project *);
void project_become(project *);
void project_become_undo(project *pp);
long project_next_test_number_get(project *);
int project_is_readable(project *);
long project_minimum_change_number_get(project *);
void project_minimum_change_number_set(project *, long);
bool project_reuse_change_numbers_get(project *);
void project_reuse_change_numbers_set(project *, bool);
long project_minimum_branch_number_get(project *);
void project_minimum_branch_number_set(project *, long);
bool project_skip_unlucky_get(project *);
void project_skip_unlucky_set(project *, bool);
bool project_compress_database_get(project *);
void project_compress_database_set(project *, bool);
int project_develop_end_action_get(project *);
void project_develop_end_action_set(project *, int);
bool project_protect_development_directory_get(project *);
void project_protect_development_directory_set(project *, bool);
int break_up_version_string(const char *text, long *buf, size_t buflen_max,
size_t &buflen, bool leading_punct);
void extract_version_from_project_name(string_ty **name, long *buf,
size_t buflen_max, size_t &sbuflen);
void extract_version_from_project_name(nstring &name, long *buf,
size_t buflen_max, size_t &buflen);
int project_name_ok(string_ty *);
bool project_name_ok(const nstring &name);
pconf_ty *project_pconf_get(project *);
/**
* The project_new_branch function is used to create new branches.
*
* @param pp
* The project to create the branch below.
* @param up
* The authorised user requesting the new branch.
* @param change_number
* The change number to use for the new branch.
* @param topdir
* The change (branch) directory, It is in the same place as the
* rest of the project, unless otherwise specified (i.e. not NULL).
* This makes it easy to collect the whole project tree, branches,
* info and all, in a simple tar or cpio command for archiving or
* moving.
* @param reason
* The reason the user gave on the command line, or NULL for no
* reason to be attached to the change's history.
* @returns
* A pointer to the new project represented by the new branch.
*/
project *project_new_branch(project *pp, user_ty::pointer up,
long change_number, string_ty *topdir = 0, string_ty *reason = 0);
string_ty *project_brief_description_get(project *);
/**
* The project_uuid_find function is used to locate a change given its UUID.
*
* @param pp
* The project to search. Will rewind to the trunk project
* before the search commences.
* @param uuid
* The change UUID to search for.
* @returns
* a pointer to the change with th given UUID, or NULL if no change
* has the given UUID.
*/
change::pointer project_uuid_find(project *pp, string_ty *uuid);
// vim: set ts=8 sw=4 et :
#endif // PROJECT_H