File indexing completed on 2024-04-28 16:01:33

0001 /******************************************************************************
0002  * This file is part of the libqgit2 library
0003  * Copyright (c) 2011 Laszlo Papp <djszapi@archlinux.us>
0004  * Copyright (C) 2013 Leonardo Giordani
0005  *
0006  * This library is free software; you can redistribute it and/or
0007  * modify it under the terms of the GNU Lesser General Public
0008  * License as published by the Free Software Foundation; either
0009  * version 2.1 of the License, or (at your option) any later version.
0010  *
0011  * This library is distributed in the hope that it will be useful,
0012  * but WITHOUT ANY WARRANTY; without even the implied warranty of
0013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
0014  * Lesser General Public License for more details.
0015  *
0016  * You should have received a copy of the GNU Lesser General Public
0017  * License along with this library; if not, write to the Free Software
0018  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
0019  */
0020 
0021 #ifndef LIBQGIT2_REPOSITORY_H
0022 #define LIBQGIT2_REPOSITORY_H
0023 
0024 #include <QtCore/QSharedPointer>
0025 #include <QtCore/QStringList>
0026 #include <QtCore/QObject>
0027 #include <QtCore/QMap>
0028 
0029 // #include "libqgit2_export.h"
0030 
0031 #include "qgitcommit.h"
0032 #include "qgitdatabase.h"
0033 #include "qgitobject.h"
0034 #include "qgitref.h"
0035 #include "qgittree.h"
0036 #include "qgitindex.h"
0037 #include "qgitstatuslist.h"
0038 #include "qgitstatusoptions.h"
0039 #include "qgitcheckoutoptions.h"
0040 #include "qgitmergeoptions.h"
0041 #include "qgitcherrypickoptions.h"
0042 #include "qgitrebase.h"
0043 #include "qgitrebaseoptions.h"
0044 
0045 namespace LibQGit2
0046 {
0047     class Commit;
0048     class Config;
0049     class Tag;
0050     class Tree;
0051     class Blob;
0052     class Signature;
0053     class Credentials;
0054     class Remote;
0055     class Diff;
0056 
0057     /**
0058      * @brief Wrapper class for git_repository.
0059      * Represents a Git repository.
0060      *
0061      * @ingroup LibQGit2
0062      * @{
0063      */
0064     class LIBQGIT2_EXPORT Repository : public QObject
0065     {
0066             Q_OBJECT
0067 
0068         public:
0069 
0070             /**
0071              * Construct a wrapper around a libgit2 repository pointer.
0072              *
0073              * If `own` is true, this Repository takes ownership of the pointer, and makes
0074              * sure it is freed when the owner is deleted, unless there are other instances
0075              * sharing the ownership. If `own` is true, the pointer must not be freed manually,
0076              * and must not be passed to another Repository instance also with `own` true.
0077              */
0078             explicit Repository(git_repository *repository = 0, bool own = false);
0079 
0080             /**
0081              * Copy constructor; creates a copy of the object, sharing the same underlaying data
0082              * structure.
0083              */
0084             Repository(const Repository& other);
0085 
0086             /**
0087              * Destruct a previously allocated repository
0088              */
0089             ~Repository();
0090 
0091             /**
0092              * Look for a git repository and return its path. The lookup start from startPath and
0093              * walk across parent directories if nothing has been found. The lookup ends when the
0094              * first repository is found, or when reaching a directory that is referenced in
0095              * ceilingDirs, or when the filesystem changes (unless acrossFs is true).
0096              *
0097              * The method will automatically detect if the repository is bare (if there is a
0098              * repository).
0099              *
0100              * The function will only return successfully if a repository was found, otherwise an
0101              * exception is thrown, providing an error message.
0102              *
0103              * @param startPath
0104              * The base path where the lookup starts.
0105              *
0106              * @param acrossFs
0107              * If true, then the lookup will not stop when a filesystem device change is detected
0108              * while exploring parent directories.
0109              *
0110              * @param ceilingDirs
0111              * A list of absolute symbolic link free paths. The lookup will stop if any of these
0112              * paths are reached. Note that the lookup always performs on startPath no matter if
0113              * startPath appears in ceilingDirs.
0114              *
0115              * @return The path of the found repository
0116              * @throws LibQGit2::Exception
0117              */
0118             static QString discover(const QString& startPath,
0119                                     bool acrossFs = false,
0120                                     const QStringList& ceilingDirs = QStringList());
0121 
0122             /**
0123              * Constructs a new Git repository in the given folder.
0124              *
0125              * @param path the path to the repository
0126              * @param isBare if true, a Git repository without a working directory is created
0127              * at the pointed path. If false, provided path will be considered as the working
0128              * directory into which the .git directory will be created.
0129              *
0130              * @throws LibQGit2::Exception
0131              */
0132             void init(const QString& path, bool isBare = false);
0133 
0134             /**
0135              * Open a git repository.
0136              *
0137              * The 'path' argument must point to an existing git repository
0138              * folder, e.g.
0139              *
0140              * /path/to/my_repo/.git/ (normal repository)
0141              * objects/
0142              * index
0143              * HEAD
0144              *
0145              * /path/to/bare_repo/ (bare repository)
0146              * objects/
0147              * index
0148              * HEAD
0149              *
0150              * The method will automatically detect if 'path' is a normal
0151              * or bare repository or fail is 'path' is neither.
0152              *
0153              * @param path the path to the repository
0154              * @throws LibQGit2::Exception
0155              */
0156             void open(const QString& path);
0157 
0158             /**
0159              * Convenience function for finding and opening a git repository.
0160              *
0161              * Calls discover() with the given arguments, and passes the result to open().
0162              *
0163              * @throws LibQGit2::Exception
0164              */
0165             void discoverAndOpen(const QString &startPath,
0166                                  bool acrossFs = false,
0167                                  const QStringList &ceilingDirs = QStringList());
0168 
0169             /**
0170              * Retrieve and resolve the reference pointed at by HEAD.
0171              *
0172              * @throws LibQGit2::Exception
0173              */
0174             Reference head() const;
0175 
0176             /**
0177              * Check if a repository's HEAD is detached
0178              *
0179              * A repository's HEAD is detached when it points directly to a commit
0180              * instead of a branch.
0181              *
0182              * @throws LibQGit2::Exception
0183              */
0184             bool isHeadDetached() const;
0185 
0186             /**
0187              * Check if the current branch is unborn
0188              *
0189              * An unborn branch is one named from HEAD but which doesn't exist
0190              * in the refs namespace, because it doesn't have any commit to point to.
0191              *
0192              * @throws LibQGit2::Exception
0193              */
0194             bool isHeadUnborn() const;
0195 
0196             /**
0197              * Check if a repository is empty
0198              *
0199              * An empty repository has just been initialized and contains
0200              * no commits.
0201              *
0202              * @throws LibQGit2::Exception
0203              */
0204             bool isEmpty() const;
0205 
0206             /**
0207              * Check if a repository is bare
0208              *
0209              * @throws LibQGit2::Exception
0210              */
0211             bool isBare() const;
0212 
0213             /**
0214              * The name equals the repositories working directory name.
0215              * In case of a bare repository, the name equals the repositorie's directory.
0216              */
0217             QString name() const;
0218 
0219             /**
0220              * Get the path to the repository
0221              */
0222             QString path() const;
0223 
0224             /**
0225              * Get the path to the working directory
0226              */
0227             QString workDirPath() const;
0228 
0229             /**
0230              * The repositories configuration file. Includes the global git configuration file.
0231              */
0232             Config configuration() const;
0233 
0234             /**
0235              * Lookup a reference by its name in a repository.
0236              *
0237              * @throws LibQGit2::Exception
0238              * @return The reference with the given name
0239              */
0240             Reference lookupRef(const QString& name) const;
0241 
0242             /**
0243              * Lookup a reference by its name in a repository and returns the oid of its target.
0244              *
0245              * @throws LibQGit2::Exception
0246              * @return The OId of the target
0247              */
0248             OId lookupRefOId(const QString& name) const;
0249 
0250             /**
0251              * Lookup a reference by its shorthand name in a repository.
0252              *
0253              * @throws LibQGit2::Exception
0254              * @return The reference with the given name
0255              */
0256             Reference lookupShorthandRef(const QString& shorthand) const;
0257 
0258             /**
0259              * Lookup a commit object from a repository.
0260              *
0261              * @throws LibQGit2::Exception
0262              */
0263             Commit lookupCommit(const OId& oid) const;
0264 
0265             /**
0266              * Lookup a tag object from the repository.
0267              *
0268              * @throws LibQGit2::Exception
0269              */
0270             Tag lookupTag(const OId& oid) const;
0271 
0272             /**
0273              * Lookup a tree object from the repository.
0274              *
0275              * @throws LibQGit2::Exception
0276              */
0277             Tree lookupTree(const OId& oid) const;
0278 
0279             /**
0280              * Lookup a blob object from a repository.
0281              *
0282              * @throws LibQGit2::Exception
0283              */
0284             Blob lookupBlob(const OId& oid) const;
0285 
0286             /**
0287              * Lookup a reference to one of the objects in a repostory.
0288              *
0289              * @throws LibQGit2::Exception
0290              */
0291             Object lookupAny(const OId& oid) const;
0292 
0293             /**
0294              * @brief Lookup an \c Object by a revision specifier.
0295              *
0296              * See `man gitrevisions`, or
0297              * [the Git documentation](http://git-scm.com/docs/git-rev-parse.html#_specifying_revisions)
0298              * for information about the accepted syntax.
0299              * @param revspec the revision specifier.
0300              * @throws LibQGit2::Exception
0301              * @return The found object if any.
0302              */
0303             Object lookupRevision(const QString &revspec) const;
0304 
0305             /**
0306              * Create a new object id reference.
0307              *
0308              * The reference will be created in the repository and written
0309              * to the disk.
0310              *
0311              * @param name The name of the reference
0312              * @param oid The target of the reference
0313              * @param overwrite If there already exists a reference with the same name, whether to overwrite it
0314              * @param message The one line long message to be appended to the reflog
0315              * @throws LibQGit2::Exception
0316              */
0317             Reference createRef(const QString& name, const OId& oid, bool overwrite = true, const QString &message = QString());
0318 
0319             /**
0320              * Create a new symbolic reference.
0321              *
0322              * The reference will be created in the repository and written
0323              * to the disk.
0324              *
0325              * @param name The name of the reference
0326              * @param target The target of the reference
0327              * @param overwrite If there already exists a reference with the same name, whether to overwrite it
0328              * @param message The one line long message to be appended to the reflog
0329              * @throws LibQGit2::Exception
0330              */
0331             Reference createSymbolicRef(const QString& name, const QString& target, bool overwrite = true, const QString &message = QString());
0332 
0333             /**
0334              * Create a new commit in the repository.
0335              *
0336              * @param tree The Tree to be used for the new Commit.
0337              * @param parents The parent Commits for the new Commit. Can be empty for the root (initial)
0338              *        Commit to the repository.
0339              * @param author Author signature.
0340              * @param committer Committer signature.
0341              * @param message The message for the new Commit.
0342              * @param ref Name of the reference that will be updated to point to this commit. If the
0343              *        reference is not direct, it will be resolved to a direct reference. Use "HEAD" to
0344              *        update the HEAD of the current branch and make it point to this commit. If the
0345              *        reference doesn't exist yet, it will be created. If it does exist, the first
0346              *        parent must be the tip of this branch.
0347              * @return The OId of the newly created commit.
0348              * @throws LibQGit2::Exception
0349              */
0350             OId createCommit(const Tree& tree, const QList<Commit>& parents, const Signature& author, const Signature& committer, const QString& message, const QString& ref = QString());
0351 
0352             /**
0353              * Create a new lightweight tag pointing at a target object
0354              *
0355              * A new direct reference will be created pointing to
0356              * this target object. If `force` is true and a reference
0357              * already exists with the given name, it'll be replaced.
0358              *
0359              * @throws LibQGit2::Exception
0360              */
0361             OId createTag(const QString& name,
0362                               const Object& target,
0363                               bool overwrite = true);
0364 
0365             /**
0366              * Create a new tag in the repository from an object
0367              *
0368              * A new reference will also be created pointing to
0369              * this tag object. If `overwrite` is true and a reference
0370              * already exists with the given name, it'll be replaced.
0371              *
0372              * @throws LibQGit2::Exception
0373              */
0374             OId createTag(const QString& name,
0375                               const Object& target,
0376                               const Signature& tagger,
0377                               const QString& message,
0378                               bool overwrite = true);
0379 
0380             /**
0381              * Delete an existing tag reference.
0382              *
0383              * @throws LibQGit2::Exception
0384              */
0385             void deleteTag(const QString& name);
0386 
0387             /**
0388              * Read a file from the working folder of a repository
0389              * and write it to the Object Database as a loose blob
0390              *
0391              * @throws LibQGit2::Exception
0392              */
0393             OId createBlobFromFile(const QString& path);
0394 
0395             /**
0396              * Write an in-memory buffer to the ODB as a blob
0397              *
0398              * @throws LibQGit2::Exception
0399              */
0400             OId createBlobFromBuffer(const QByteArray& buffer);
0401 
0402             /**
0403              * Creates a new branch to this repository.
0404              * @param branchName The name of the new branch.
0405              * @param target The starting point of the branch, i.e. where the new branch will point to. Defaults to HEAD.
0406              * @param force Controls whether to overwrite an already existing branch.
0407              * @return A reference to the newly created branch
0408              * @throws LibQGit2::Exception
0409              */
0410             Reference createBranch(const QString &branchName, const Commit &target = Commit(), bool force = false);
0411 
0412             /**
0413              * Deletes a local branch.
0414              * @param branchName The name of the branch.
0415              * @throws LibQGit2::Exception
0416              */
0417             void deleteBranch(const QString &branchName);
0418 
0419             /**
0420              * Cherry-picks a commit.
0421              * @param commit The commit to cherry-pick.
0422              * @param opts The options specifying how the cherry-pick is made.
0423              * @throws LibQGit2::Exception
0424              */
0425             void cherryPick(const Commit &commit, const CherryPickOptions &opts = CherryPickOptions());
0426 
0427             /**
0428              * Create a list with all the tags in the Repository
0429              * which name match a defined pattern
0430              *
0431              * If an empty pattern is provided, all the tags
0432              * will be returned.
0433              *
0434              * @param pattern Standard fnmatch pattern
0435              * @throws LibQGit2::Exception
0436              */
0437             QStringList listTags(const QString& pattern = QString()) const;
0438 
0439             /**
0440              * Create a list with all references in the Repository.
0441              *
0442              * @param pattern Standard fnmatch pattern
0443              * @throws LibQGit2::Exception
0444              */
0445             QStringList listReferences() const;
0446 
0447             /**
0448              * @brief Get the object database behind a Git repository
0449              *
0450              * @return a pointer to the object db
0451              */
0452             LibQGit2::Database database() const;
0453 
0454             /**
0455              * @brief Get the Index file of a Git repository
0456              *
0457              * This is a cheap operation; the index is only opened on the first call,
0458              * and subsequent calls only retrieve the previous pointer.
0459              *
0460              * @throws LibQGit2::Exception
0461              * @return The index file of the repository
0462              */
0463             Index index() const;
0464 
0465             /**
0466              * @brief Get the status information of the Git repository
0467              *
0468              * This function returns the status of the repository entries, according to
0469              * the given options.
0470              *
0471              * @throws LibQGit2::Exception
0472              * @return The list of status entries
0473              */
0474             StatusList status(const StatusOptions &options) const;
0475 
0476             /**
0477              * How two nodes are related to each other in a graph.
0478              */
0479             struct GraphRelationship {
0480                 /** How many steps one node is ahead of another. */
0481                 size_t ahead;
0482                 /** How many steps one node is behind of another. */
0483                 size_t behind;
0484             };
0485 
0486             /**
0487              * Solves how the \a local commit is situated in the commit tree in relation to the
0488              * \a upstream commit. Both arguments can be any arbitrary commits in this repository
0489              * but it's useful to think them as the local branch tip commit and its corresponding
0490              * remote branch tip.
0491              *
0492              * @note The \a local commit can be both ahead of and behind from the \a upstream
0493              * commit if the branches have diverged.
0494              *
0495              * @param local The local commit.
0496              * @param upstream The upstream commit.
0497              * @return The relationship between the commits.
0498              * @throws LibQGit2::Exception
0499              */
0500             GraphRelationship commitRelationship(const Commit &local, const Commit &upstream) const;
0501 
0502             /**
0503              * @brief Makes a Diff between two Trees.
0504              *
0505              * Either Tree argument can be a NULL Tree, but not both.
0506              *
0507              * @param oldTree the Tree on the `old' side of the diff.
0508              * @param newTree the Tree on the `new' side of the diff.
0509              * @throws LibQGit2::Exception
0510              * @return The Diff between the provided Trees.
0511              */
0512             Diff diffTrees(const Tree &oldTree, const Tree &newTree) const;
0513 
0514             /**
0515              * Finds a merge base between two commits.
0516              * @param one The first Commit.
0517              * @param two The second Commit.
0518              * @return The merge base Commit.
0519              * @throws LibQGit2::Exception
0520              */
0521             Commit mergeBase(const Commit &one, const Commit &two) const;
0522 
0523             /**
0524              * Merge two trees, producing an Index that reflects the result of the merge. The index
0525              * may be written as-is to the working directory or checked out. If the index is to be
0526              * converted to a tree, the caller should resolve any conflicts that arose as part of the merge.
0527              *
0528              * At least one of \a our or \a their must be a valid Tree.
0529              *
0530              * @param our The tree that reflects the destination tree.
0531              * @param their The tree to merge into the destination tree.
0532              * @param ancestor The common ancestor between the trees. May be null.
0533              * @param opts The merge options.
0534              * @return The merged index.
0535              */
0536             Index mergeTrees(const Tree &our, const Tree &their, const Tree &ancestor = Tree(), const MergeOptions &opts = MergeOptions());
0537 
0538             /**
0539              * @brief Sets a \c Credentials object to be used for a named remote.
0540              *
0541              * Some remotes require authentication when communicating with them. Authentication
0542              * is performed by using \c Credentials objects. Each named remote can have its own
0543              * \c Credentials object. The credentials for a remote must be set using this method
0544              * before trying to communicate with it.
0545              *
0546              * @param remoteName the name of the remote
0547              * @param credentials the \c Credentials to be used for the remote
0548              */
0549             void setRemoteCredentials(const QString& remoteName, Credentials credentials);
0550 
0551             /**
0552             * Clone a git repository.
0553             *
0554             * Signal cloneProgress(int) is emitted with progress in percent.
0555             *
0556             * @param url URL of the git repository
0557             * @param path non-existing directory for the new clone
0558             * @throws LibQGit2::Exception
0559             */
0560             void clone(const QString& url, const QString& path);
0561 
0562             /**
0563             * Add remote repository.
0564             *
0565             * @param name name of the remote
0566             * @param url URL of the remote git repository
0567             * @param changeUrlIfExists affects the behaviour if the remote already exists:
0568             * if true changes the remote's URL, if false throws an exception.
0569             * @throws LibQGit2::Exception
0570             */
0571             void remoteAdd(const QString& name, const QString& url, bool changeUrlIfExists = false);
0572 
0573             /**
0574              * Gets a named remote from this repository. The caller is responsible for
0575              * managing the returned object.
0576              * @param remoteName the name of the remote
0577              * @param parent the parent for the object that is returned
0578              * @throws LibQGit2::Exception
0579              */
0580             Remote* remote(const QString &remoteName, QObject *parent = 0) const;
0581 
0582             /**
0583             * Fetch from known remote repository.
0584             *
0585             * @param remote Name of the remote repository (e.g. "origin")
0586             * @param head Name of head to fetch (e.g. "master"). If left as the default
0587             *        the fetch heads configured for the remote are used.
0588             * @param message The message to insert into the reflogs. If left as the
0589             *        default (a null string), a message "fetch <name>" is used , where <name>
0590             *        is the name of the remote (or its url, for in-memory remotes).
0591             * @throws LibQGit2::Exception
0592             */
0593             void fetch(const QString& remote, const QString& head = QString(), const QString &message = QString());
0594 
0595             QStringList remoteBranches(const QString& remoteName);
0596 
0597 
0598             /**
0599              * Checkout a treeish, i.e. a Commit, Tag or Tree.
0600              * @param treeish the Object to checkout
0601              * @param opts the options used in the checkout
0602              * @throws LibQGit2::Exception
0603              */
0604             void checkoutTree(const Object &treeish, const CheckoutOptions &opts = CheckoutOptions());
0605 
0606             /**
0607              * Updates files in the index and the working tree to match the content
0608              * of the commit pointed at by HEAD.
0609              * @param opts the options used in the checkout
0610              * @throws LibQGit2::Exception
0611              */
0612             void checkoutHead(const CheckoutOptions &opts = CheckoutOptions());
0613 
0614             /**
0615             * Checkout a remote branch without creating a local branch.
0616             *
0617             * @param branch  branch name
0618             * @param opts the options used in the checkout
0619             * @param remote  remote which should be used, default is 'origin'
0620             * @throws LibQGit2::Exception
0621             */
0622             void checkoutRemote(const QString& branch, const CheckoutOptions &opts = CheckoutOptions(), const QString& remote = "origin");
0623 
0624             /**
0625              * Types of reset operation.
0626              */
0627             enum ResetType {
0628                 Soft,      ///< Move the head to the given commit
0629                 Mixed,     ///< Soft plus reset index to the commit
0630                 Hard       ///< Mixed plus changes in working tree discarded
0631             };
0632 
0633             /**
0634              * Sets the current head to the specified \a target oid and optionally
0635              * resets the index and working tree to match.
0636              *
0637              * @param target the committish to which the HEAD should be moved to
0638              * @param type what kind of reset should be performed
0639              * @throws LibQGit2::Exception
0640              */
0641             void reset(const Object &target, ResetType type = Mixed);
0642 
0643             /**
0644              * Initializes a rebase object for rebasing the changes in \a branch
0645              * relative to \a upstream onto another branch.
0646              *
0647              * @param branch The terminal commit to rebase
0648              * @param upstream The commit to begin rebasing from, or \c null to rebase all
0649              *                 reachable commits
0650              * @param onto The branch to rebase onto, or \c null to rebase onto the given
0651              *             upstream
0652              * @param opts Options to specify how rebase is performed
0653              * @return The initialized rebase object
0654              * @throws LibQGit2::Exception
0655              */
0656             Rebase rebase(const Reference &branch, const Reference &upstream, const Reference &onto, const RebaseOptions &opts);
0657 
0658             /**
0659              * Checks if the repository's ignore rules would ignore the given \a path.
0660              *
0661              * If \a path is relative it is considered to be relative to the Repository's
0662              * working directory. If \a path is absolute it must point to a location
0663              * within this Repository's working directory or an exception is thrown.
0664              *
0665              * @throws LibQGit2::Exception
0666              */
0667             bool shouldIgnore(const QString &path) const;
0668 
0669             struct Identity {
0670                 QString name;
0671                 QString email;
0672             };
0673 
0674             /**
0675              * Set the identity to be used for writing reflogs.
0676              *
0677              * @param id The name and email to use for the reflog entries
0678              *
0679              * If both \c name and \c email are set in the given \a id, then \a id will be
0680              * used to write to the reflog. Set either \c name or \c email to empty string
0681              * to unset. When unset, the identity will be taken from the repository's
0682              * configuration.
0683              *
0684              * @throws LibQGit2::Exception
0685              */
0686             void setIdentity(const Identity &id);
0687 
0688             /**
0689              * Retrieve the configured identity to use for reflogs.
0690              *
0691              * @throws LibQGit2::Exception
0692              */
0693             Identity identity() const;
0694 
0695             git_repository* data() const;
0696             const git_repository* constData() const;
0697 
0698         signals:
0699             void cloneProgress(int);
0700             void fetchProgress(int);
0701 
0702         private:
0703             class Private;
0704             QSharedPointer<Private> d_ptr;
0705             Q_DECLARE_PRIVATE()
0706     };
0707 
0708     /**@}*/
0709 }
0710 
0711 #endif // LIBQGIT2_REPOSITORY_H