1 /*
2  * ====================================================================
3  * Copyright (c) 2002-2009 The RapidSvn Group.  All rights reserved.
4  *
5  * This program is free software: you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation, either version 3 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program (in the file GPL.txt.
17  * If not, see <http://www.gnu.org/licenses/>.
18  *
19  * This software consists of voluntary contributions made by many
20  * individuals.  For exact contribution history, see the revision
21  * history and logs, available at http://rapidsvn.tigris.org/.
22  * ====================================================================
23  */
24 
25 #ifndef _SVNCPP_CLIENT_H_
26 #define _SVNCPP_CLIENT_H_
27 
28 // Ignore MSVC 6 compiler warning
29 #if defined (_MSC_VER) && _MSC_VER <= 1200
30 // debug symbol truncated
31 #pragma warning (disable: 4786)
32 // C++ exception specification
33 #pragma warning (disable: 4290)
34 #endif
35 
36 // Ignore MSVC 7,8,9 compiler warnings
37 #if defined (_MSC_VER) && _MSC_VER > 1200 && _MSC_VER <= 1500
38 // C++ exception specification
39 #pragma warning (disable: 4290)
40 #endif
41 
42 
43 // stl
44 #include "kdevsvncpp/vector_wrapper.hpp"
45 #include "kdevsvncpp/utility_wrapper.hpp"
46 #include "kdevsvncpp/map_wrapper.hpp"
47 
48 // svncpp
49 #include "kdevsvncpp/context.hpp"
50 #include "kdevsvncpp/exception.hpp"
51 #include "kdevsvncpp/path.hpp"
52 #include "kdevsvncpp/entry.hpp"
53 #include "kdevsvncpp/revision.hpp"
54 #include "kdevsvncpp/log_entry.hpp"
55 #include "kdevsvncpp/annotate_line.hpp"
56 
57 
58 namespace svn
59 {
60   // forward declarations
61   class Context;
62   class DirEntry;
63   class Info;
64   class Status;
65   class Targets;
66 
67   typedef std::vector<AnnotateLine> AnnotatedFile;
68   typedef std::vector<DirEntry> DirEntries;
69   typedef std::vector<Info> InfoVector;
70   typedef std::vector<LogEntry> LogEntries;
71   typedef std::vector<Status> StatusEntries;
72 
73 
74   // map of property names to values
75   typedef std::map<std::string,std::string> PropertiesMap;
76   // pair of path, PropertiesMap
77   typedef std::pair<std::string, PropertiesMap> PathPropertiesMapEntry;
78   // vector of path, Properties pairs
79   typedef std::vector<PathPropertiesMapEntry> PathPropertiesMapList;
80 
81   /**
82    * These flags can be passed to the status function to filter
83    * the files
84    *
85    * @see status
86    */
87   struct StatusFilter
88   {
89 public:
90     bool showUnversioned;
91     bool showUnmodified;
92     bool showModified;    ///< this includes @a showConflicted as well
93     bool showConflicted;
94     bool showIgnored;
95     bool showExternals;
96 
StatusFiltersvn::StatusFilter97     StatusFilter()
98       : showUnversioned(false), showUnmodified(false),
99         showModified(false), showConflicted(false),
100         showExternals(false)
101     {
102     }
103   };
104 
105 
106   /**
107    * Subversion client API.
108    */
109   class Client
110   {
111   public:
112     /**
113      * Initializes the primary memory pool.
114      */
115     Client(Context * context = nullptr);
116 
117     virtual ~Client();
118 
119     /**
120      * @return returns the Client context
121      */
122     const Context *
123     getContext() const;
124 
125     /**
126      * @return returns the Client context
127      */
128     Context *
129     getContext();
130 
131     /**
132      * sets the client context
133      * you have to make sure the old context
134      * is de-allocated
135      *
136      * @param context new context to use
137      */
138     void
139     setContext(Context * context = NULL);
140 
141     /**
142      * Enumerates all files/dirs at a given path.
143      *
144      * Throws an exception if an error occurs
145      *
146      * @param path Path to explore.
147      * @param descend Recurse into subdirectories if existant.
148      * @param get_all Return all entries, not just the interesting ones.
149      * @param update Query the repository for updates.
150      * @param no_ignore Disregard default and svn:ignore property ignores.
151      * @param ignore_externals Disregard external files.
152      * @return vector with Status entries.
153      */
154     StatusEntries
155     status(const char * path,
156            const bool descend = false,
157            const bool get_all = true,
158            const bool update = false,
159            const bool no_ignore = false,
160            const bool ignore_externals = false);
161 
162     /**
163      * Enumerates all files/dirs matchin the parameter @a filter
164      * at @a path and returns them in the vector @a statusEntries
165      *
166      * Throws an exception if an error occurs
167      *
168      * @since New in 0.9.7
169      *
170      * @param path Path to explore.
171      * @param filter use a combination of the @a SHOW_* values to filter the
172      *        output
173      * @param descend Recurse into subdirectories if existant.
174      * @param update Query the repository for updates.
175      * @param entries vector with Status entries
176      *
177      * @return current revnum
178      */
179     svn_revnum_t
180     status(const char * path,
181            const StatusFilter & filter,
182            const bool descend,
183            const bool update,
184            StatusEntries & entries);
185 
186 
187     /**
188      * Executes a revision checkout.
189      * @param moduleName name of the module to checkout.
190      * @param destPath destination directory for checkout.
191      * @param revision the revision number to checkout. If the number is -1
192      *                 then it will checkout the latest revision.
193      * @param recurse whether you want it to checkout files recursively.
194      * @param ignore_externals whether you want get external resources too.
195      * @param peg_revision peg revision to checkout, by default current.
196      * @exception ClientException
197      */
198     svn_revnum_t
199     checkout(const char * moduleName,
200              const Path & destPath,
201              const Revision & revision,
202              bool recurse,
203              bool ignore_externals = false,
204              const Revision & peg_revision = Revision::UNSPECIFIED);
205 
206     /**
207      * relocate wc @a from to @a to
208      * @exception ClientException
209      */
210     void
211     relocate(const Path & path, const char *from_url,
212              const char *to_url, bool recurse);
213 
214     /**
215      * Sets a single file for deletion.
216      * @exception ClientException
217      */
218     void
219     remove(const Path & path, bool force);
220 
221     /**
222      * Sets files for deletion.
223      *
224      * @param targets targets to delete
225      * @param force force if files are locally modified
226      * @exception ClientException
227      */
228     void
229     remove(const Targets & targets,
230            bool force);
231 
232     /**
233      * Sets files to lock.
234      *
235      * @param targets targets to lock
236      * @param force force setting/stealing lock
237      * @param comment writing comment about lock setting is necessary
238      * @exception ClientException
239      */
240     void
241     lock(const Targets & targets, bool force,
242          const char * comment);
243 
244     /**
245      * Sets files to unlock.
246      *
247      * @param targets targets to unlock
248      * @param force force unlock even if lock belongs to another user
249      * @exception ClientException
250      */
251     void
252     unlock(const Targets & targets, bool force);
253 
254     /**
255      * Reverts a couple of files to a pristiner state.
256      * @exception ClientException
257      */
258     void
259     revert(const Targets & targets, bool recurse);
260 
261     /**
262      * Adds a file to the repository.
263      * @exception ClientException
264      */
265     void
266     add(const Path & path, bool recurse);
267 
268     /**
269      * Updates the file or directory.
270      * @param targets target files.
271      * @param revision the revision number to checkout.
272      *                 Revision::HEAD will checkout the
273      *                 latest revision.
274      * @param recurse recursively update.
275      * @param ignore_externals don't affect external destinations.
276      * @exception ClientException
277      *
278      * @return a vector with resulting revisions
279      */
280     std::vector<svn_revnum_t>
281     update(const Targets & targets,
282            const Revision & revision,
283            bool recurse,
284            bool ignore_externals);
285 
286     svn_revnum_t
287     update(const Path & path,
288            const Revision & revision,
289            bool recurse,
290            bool ignore_externals);
291 
292     /**
293      * Retrieves the contents for a specific @a revision of
294      * a @a path
295      *
296      * @param path path of file or directory
297      * @param revision revision to retrieve
298      * @param peg_revision peg revision to retrieve,
299      *        by default is the latest one
300      * @return contents of the file
301      */
302     std::string
303     cat(const Path & path,
304         const Revision & revision,
305         const Revision & peg_revision = Revision::UNSPECIFIED);
306 
307 
308     /**
309      * Retrieves the contents for a specific @a revision of
310      * a @a path and saves it to the destination file @a dstPath.
311      *
312      * If @a dstPath is empty (""), then this path will be
313      * constructed from the temporary directory on this system
314      * and the filename in @a path. @a dstPath will still have
315      * the file extension from @a path and uniqueness of the
316      * temporary filename will be ensured.
317      *
318      * @param dstPath Filename in which the contents
319      *                of the file will be saved.
320      * @param path path or url
321      * @param peg_revision peg revision to retrieve, by default is the latest one
322      */
323     void
324     get(Path & dstPath,
325         const Path & path,
326         const Revision & revision,
327         const Revision & peg_revision = Revision::UNSPECIFIED);
328 
329 
330     /**
331      * Retrieves the contents for a specific @a revision of
332      * a @a path
333      *
334      * @param path path of file or directory
335      * @param revisionStart revision to retrieve
336      * @param revisionEnd revision to retrieve
337      * @return contents of the file
338      */
339     AnnotatedFile *
340     annotate(const Path & path,
341              const Revision & revisionStart,
342              const Revision & revisionEnd);
343 
344     /**
345      * Commits changes to the repository. This usually requires
346      * authentication, see Auth.
347      * @return Returns a long representing the revision. It returns a
348      *         -1 if the revision number is invalid.
349      * @param targets files to commit.
350      * @param message log message.
351      * @param recurse whether the operation should be done recursively.
352      * @param keep_locks whether to preserve locks or to release them after commit
353      * @exception ClientException
354      */
355     svn_revnum_t
356     commit(const Targets & targets,
357            const char * message,
358            bool recurse,
359            bool keep_locks = false);
360 
361     /**
362      * Copies a versioned file with the history preserved.
363      * @exception ClientException
364      */
365     void
366     copy(const Path & srcPath,
367          const Revision & srcRevision,
368          const Path & destPath);
369 
370     /**
371      * Moves or renames a file.
372      * @exception ClientException
373      */
374     void
375     move(const Path & srcPath,
376          const Revision & srcRevision,
377          const Path & destPath,
378          bool force);
379 
380     /**
381      * Creates a directory directly in a repository or creates a
382      * directory on disk and schedules it for addition. If <i>path</i>
383      * is a URL then authentication is usually required, see Auth.
384      *
385      * @exception ClientException
386      */
387     void
388     mkdir(const Path & path);
389 
390     void
391     mkdir(const Targets & targets);
392 
393     /**
394      * Recursively cleans up a local directory, finishing any
395      * incomplete operations, removing lockfiles, etc.
396      * @param path a local directory.
397      * @exception ClientException
398      */
399     void
400     cleanup(const Path & path);
401 
402     /**
403      * Removes the 'conflicted' state on a file.
404      * @exception ClientException
405      */
406     void
407     resolved(const Path & path, bool recurse);
408 
409     /**
410      * Export into file or directory TO_PATH from local or remote FROM_PATH
411      * @param from_path path to import
412      * @param to_path where to import
413      * @param revision revision of files in source repository or working copy
414      * @param overwrite overwrite existing files in to_path
415      * @param ignore_externals whether to ignore external sources in from_path
416      * @param native_eol which EOL to use when exporting, usually different for
417      * different OSs
418      * @exception ClientException
419      */
420     void
421     doExport(const Path & from_path,
422              const Path & to_path,
423              const Revision & revision,
424              bool overwrite = false,
425              const Revision & peg_revision = Revision::UNSPECIFIED,
426              bool ignore_externals = false,
427              bool recurse = true,
428              const char * native_eol = NULL);
429 
430     /**
431      * Update local copy to mirror a new url. This excapsulates the
432      * svn_client_switch() client method.
433      * @exception ClientException
434      */
435     svn_revnum_t
436     doSwitch(const Path & path, const char * url,
437              const Revision & revision,
438              bool recurse);
439 
440     /**
441      * Import file or directory PATH into repository directory URL at
442      * head.  This usually requires authentication, see Auth.
443      * @param path path to import
444      * @param message log message.
445      * @exception ClientException
446      */
447     void
448     import(const Path & path,
449            const char * url,
450            const char * message,
451            bool recurse);
452     void
453     import(const Path & path,
454            const Path & url,
455            const char * message,
456            bool recurse);
457 
458 
459     /**
460      * Merge changes from two paths into a new local path.
461      * @exception ClientException
462      */
463     void
464     merge(const Path & path1, const Revision & revision1,
465           const Path & path2, const Revision & revision2,
466           const Path & localPath, bool force,
467           bool recurse,
468           bool notice_ancestry = false,
469           bool dry_run = false);
470 
471 
472     /**
473      * retrieve information about the given path
474      * or URL
475      *
476      * @see Client::status
477      * @see Info
478      */
479     InfoVector
480     info(const Path & pathOrUrl,
481          bool recurse=false,
482          const Revision & revision = Revision::UNSPECIFIED,
483          const Revision & pegRevision = Revision::UNSPECIFIED);
484 
485 
486     /**
487      * Retrieve log information for the given path
488      * Loads the log messages result set. The first
489      * entry  is the youngest revision.
490      *
491      * You can use the constants Revision::START and
492      * Revision::HEAD
493 
494      * @return a vector with log entries
495      */
496     const LogEntries *
497     log(const char * path,
498         const Revision & revisionStart,
499         const Revision & revisionEnd,
500         bool discoverChangedPaths = false,
501         bool strictNodeHistory = true);
502 
503     /**
504      * Produce diff output which describes the delta between
505      * @a path/@a revision1 and @a path/@a revision2. @a path
506      * can be either a working-copy path or a URL.
507      *
508      * A ClientException will be thrown if either @a revision1 or
509      * @a revision2 has an `unspecified' or unrecognized `kind'.
510      *
511      * @param tmpPath prefix for a temporary directory needed by diff.
512      * Filenames will have ".tmp" and similar added to this prefix in
513      * order to ensure uniqueness.
514      * @param path path of the file.
515      * @param revision1 one of the revisions to check.
516      * @param revision2 the other revision.
517      * @param recurse whether the operation should be done recursively.
518      * @param ignoreAncestry whether the files will be checked for
519      * relatedness.
520      * @param noDiffDeleted if true, no diff output will be generated
521      * on deleted files.
522      * @return delta between the files
523      * @exception ClientException
524      */
525     std::string
526     diff(const Path & tmpPath, const Path & path,
527          const Revision & revision1, const Revision & revision2,
528          const bool recurse, const bool ignoreAncestry,
529          const bool noDiffDeleted);
530 
531     /**
532      * Produce diff output which describes the delta between
533      * @a path1/@a revision1 and @a path2/@a revision2. @a path1,
534      * @a path2 can be either a working-copy path or a URL.
535      *
536      * A ClientException will be thrown if either @a revision1 or
537      * @a revision2 has an `unspecified' or unrecognized `kind'.
538      *
539      * @param tmpPath prefix for a temporary directory needed by diff.
540      * Filenames will have ".tmp" and similar added to this prefix in
541      * order to ensure uniqueness.
542      * @param path1 path of the first file corresponding to @a revision1.
543      * @param path2 path of the first file corresponding to @a revision2.
544      * @param revision1 one of the revisions to check.
545      * @param revision2 the other revision.
546      * @param recurse whether the operation should be done recursively.
547      * @param ignoreAncestry whether the files will be checked for
548      * relatedness.
549      * @param noDiffDeleted if true, no diff output will be generated
550      * on deleted files.
551      * @return delta between the files
552      * @exception ClientException
553      */
554     std::string
555     diff(const Path & tmpPath, const Path & path1, const Path & path2,
556          const Revision & revision1, const Revision & revision2,
557          const bool recurse, const bool ignoreAncestry,
558          const bool noDiffDeleted);
559 
560     /**
561      * Produce diff output which describes the delta of
562      * @a path/@a pegRevision between @a revision1 and @a revision2.
563      * @a path can be either a working-copy path or a URL.
564      *
565      * A ClientException will be thrown if either @a revision1 or
566      * @a revision2 has an `unspecified' or unrecognized `kind'.
567      *
568      * @param tmpPath prefix for a temporary directory needed by diff.
569      * Filenames will have ".tmp" and similar added to this prefix in
570      * order to ensure uniqueness.
571      * @param path path of the file.
572      * @param pegRevision the peg revision to identify the path.
573      * @param revision1 one of the revisions to check.
574      * @param revision2 the other revision.
575      * @param recurse whether the operation should be done recursively.
576      * @param ignoreAncestry whether the files will be checked for
577      * relatedness.
578      * @param noDiffDeleted if true, no diff output will be generated
579      * on deleted files.
580      * @return delta between the files
581      * @exception ClientException
582      */
583     std::string
584     diff(const Path & tmpPath, const Path & path,
585          const Revision & pegRevision, const Revision & revision1,
586          const Revision & revision2, const bool recurse,
587          const bool ignoreAncestry, const bool noDiffDeleted)
588    ;
589 
590     /**
591      * lists entries in @a pathOrUrl no matter whether local or
592      * repository
593      *
594      * @return a vector of directory entries, each with
595      *         a relative path (only filename)
596      */
597     DirEntries
598     list(const char * pathOrUrl,
599          svn_opt_revision_t * revision,
600          bool recurse);
601 
602     /**
603      * lists properties in @a path no matter whether local or
604      * repository
605      *
606      * @return PropertiesList
607      */
608     PathPropertiesMapList
609     proplist(const Path &path,
610              const Revision &revision,
611              bool recurse = false);
612 
613     /**
614      * lists one property in @a path no matter whether local or
615      * repository
616      *
617      * @return PathPropertiesMapList
618      */
619     PathPropertiesMapList
620     propget(const char * propName,
621             const Path & path,
622             const Revision & revision,
623             bool recurse = false);
624 
625     /**
626      * This method is deprecated, please use
627      * @a Property.set
628      * set property in @a path no matter whether local or
629      * repository
630      *
631      * @deprecated
632      */
633     void
634     propset(const char * propName,
635             const char * propValue,
636             const Path & path,
637             const Revision & revision,
638             bool recurse = false,
639             bool skip_checks = true);
640 
641     /**
642      * delete property in @a path no matter whether local or
643      * repository
644      *
645      */
646     void
647     propdel(const char * propName,
648             const Path & path,
649             const Revision & revision,
650             bool recurse = false);
651 
652 
653     /**
654      * lists revision properties in @a path no matter whether local or
655      * repository
656      *
657      * @return PropertiesList
658      */
659     std::pair<svn_revnum_t,PropertiesMap>
660     revproplist(const Path & path,
661                 const Revision & revision);
662 
663     /**
664      * lists one revision property in @a path no matter whether local or
665      * repository
666      *
667      * @return PropertiesList
668      */
669     std::pair<svn_revnum_t,std::string>
670     revpropget(const char * propName,
671                const Path & path,
672                const Revision & revision);
673 
674     /**
675      * set revision property in @a path no matter whether local or
676      * repository
677      *
678      * @return Revision
679      */
680     svn_revnum_t
681     revpropset(const char * propName,
682                const char * propValue,
683                const Path & path,
684                const Revision & revision,
685                bool force = false);
686 
687     /**
688      * delete revision property in @a path no matter whether local or
689      * repository
690      *
691      * @return Revision
692      */
693     svn_revnum_t
694     revpropdel(const char * propName,
695                const Path & path,
696                const Revision & revision,
697                bool force = false);
698 
699 
700     /**
701      * Add a single file into ignore list.
702     *
703      * @param path path to the file
704      * @exception ClientException
705     * @see svn:ignore property description
706      */
707     void
708     ignore(const Path & path);
709 
710     /**
711      * Add files into ignore list.
712      *
713      * @param targets targets to treat as ignored
714      * @exception ClientException
715     * @see svn:ignore property description
716      */
717     void
718     ignore(const Targets & targets);
719   private:
720     Context * m_context;
721 
722     /**
723      * disallow assignment operator
724      */
725     Client & operator= (const Client &);
726 
727     /**
728      * disallow copy constructor
729      */
730     Client(const Client &);
731   };
732 }
733 
734 #endif
735 /* -----------------------------------------------------------------
736  * local variables:
737  * eval: (load-file "../../rapidsvn-dev.el")
738  * end:
739  */
740