Управление версиями в Subversion Для Subversion 3 (в редакции 2345) Бен Коллинз-Сассман



бет34/34
Дата04.03.2016
өлшемі2.13 Mb.
#40691
түріРеферат
1   ...   26   27   28   29   30   31   32   33   34

Subversion Repository URLs


As illustrated throughout this book, Subversion uses URLs to identify versioned resources in Subversion repositories. For the most part, these URLs use the standard syntax, allowing for server names and port numbers to be specified as part of the URL:

$ svn checkout http://svn.example.com:9834/repos

But there are some nuances in Subversion's handling of URLs that are notable. For example, URLs containing the file: access method (used for local repositories) must, in accordance with convention, have either a server name of localhost or no server name at all:



$ svn checkout file:///path/to/repos

$ svn checkout file://localhost/path/to/repos



Also, users of the file: scheme on Windows platforms will need to use an unofficially «standard» syntax for accessing repositories that are on the same machine, but on a different drive than the client's current working drive. Either of the two following URL path syntaxes will work where X is the drive on which the repository resides:

C:\> svn checkout file:///X:/path/to/repos

C:\> svn checkout "file:///X|/path/to/repos"



In the second syntax, you need to quote the URL so that the vertical bar character is not interpreted as a pipe. Also, note that a URL uses ordinary slashes even though the native (non-URL) form of a path on Windows uses backslashes.

Finally, it should be noted that the Subversion client will automatically encode URLs as necessary, just like a web browser does. For example, if a URL contains a space or upper-ASCII character:

$ svn checkout "http://host/path with space/project/españa"

…then Subversion will escape the unsafe characters and behave as if you had typed:

$ svn checkout http://host/path%20with%20space/project/espa%C3%B1a



If the URL contains spaces, be sure to place it within quote marks, so that your shell treats the whole thing as a single argument to the svn program.


[34] Переменная среды окружения APPDATA указывает на папку Application Data поэтому к этой директории можно всегда обращаться как к %APPDATA%\Subversion.

[35] Anyone for potluck dinner?

[36] Если вы знакомы с XML, то синтаксис XML "Name" использует практически тот же ASCII набор.

[37] Исправление в лог сообщениях орфографических, грамматических ошибок, «просто ошибочных» записей, наверно, самые распространенные случаи использования параметра --revprop.

[38] Для определения исполняемых файлов, файловая система Windows использует расширения файлов (такие, как .EXE, .BAT и .COM).

[39] The patterns are strictly for that directory—they do not carry recursively into subdirectories.

[40] Isn't that the whole point of a build system?

[41] … or maybe even a section of a book …

[42] «You're not supposed to name it. Once you name it, you start getting attached to it.» — Mike Wazowski

[43] 606 N. Main Street, Wheaton, Illinois, is the home of the Wheaton History Center. Get it—«History Center»? It seemed appropriate….

[44] And entirely bug-free, of course!

[45] Subversion developers are good, but even the best make mistakes.

[46] The GNU diff manual page puts it this way: «An exit status of 0 means no differences were found, 1 means some differences were found, and 2 means trouble.»

Глава 8. Информация для разработчиков


Содержание

Layered Library Design

Repository Layer

Repository Access Layer

RA-DAV (Repository Access Using HTTP/DAV)

RA-SVN (Custom Protocol Repository Access)

RA-Local (Direct Repository Access)

Your RA Library Here

Client Layer

Using the APIs

The Apache Portable Runtime Library

URL and Path Requirements

Using Languages Other than C and C++

Inside the Working Copy Administration Area

The Entries File

Pristine Copies and Property Files

WebDAV

Programming with Memory Pools

Contributing to Subversion

Join the Community

Get the Source Code

Become Familiar with Community Policies

Make and Test Your Changes

Donate Your Changes

Subversion is an open-source software project developed under an Apache-style software license. The project is financially backed by CollabNet, Inc., a California-based software development company. The community that has formed around the development of Subversion always welcomes new members who can donate their time and attention to the project. Volunteers are encouraged to assist in any way they can, whether that means finding and diagnosing bugs, refining existing source code, or fleshing out whole new features.



This chapter is for those who wish to assist in the continued evolution of Subversion by actually getting their hands dirty with the source code. We will cover some of the software's more intimate details, the kind of technical nitty-gritty that those developing Subversion itself—or writing entirely new tools based on the Subversion libraries—should be aware of. If you don't foresee yourself participating with the software at such a level, feel free to skip this chapter with confidence that your experience as a Subversion user will not be affected.

Layered Library Design


Subversion has a modular design, implemented as a collection of C libraries. Each library has a well-defined purpose and interface, and most modules are said to exist in one of three main layers—the Repository Layer, the Repository Access (RA) Layer, or the Client Layer. We will examine these layers shortly, but first, see our brief inventory of Subversion's libraries in Таблица 8.1, «A Brief Inventory of the Subversion Libraries». For the sake of consistency, we will refer to the libraries by their extensionless Unix library names (e.g.: libsvn_fs, libsvn_wc, mod_dav_svn).

Таблица 8.1. A Brief Inventory of the Subversion Libraries

Library

Description

libsvn_client

Primary interface for client programs

libsvn_delta

Tree and byte-stream differencing routines

libsvn_diff

Contextual differencing and merging routines

libsvn_fs

Filesystem commons and module loader

libsvn_fs_base

The Berkeley DB filesystem back-end

libsvn_fs_fs

The native filesystem (FSFS) back-end

libsvn_ra

Repository Access commons and module loader

libsvn_ra_dav

The WebDAV Repository Access module

libsvn_ra_local

The local Repository Access module

libsvn_ra_svn

The custom protocol Repository Access module

libsvn_repos

Repository interface

libsvn_subr

Miscellaneous helpful subroutines

libsvn_wc

The working copy management library

mod_authz_svn

Apache authorization module for Subversion repositories access via WebDAV

mod_dav_svn

Apache module for mapping WebDAV operations to Subversion ones

The fact that the word «miscellaneous» only appears once in Таблица 8.1, «A Brief Inventory of the Subversion Libraries» is a good sign. The Subversion development team is serious about making sure that functionality lives in the right layer and libraries. Perhaps the greatest advantage of the modular design is its lack of complexity from a developer's point of view. As a developer, you can quickly formulate that kind of «big picture» that allows you to pinpoint the location of certain pieces of functionality with relative ease.

Another benefit of modularity is the ability to replace a given module with a whole new library that implements the same API without affecting the rest of the code base. In some sense, this happens within Subversion already. The libsvn_ra_dav, libsvn_ra_local, and libsvn_ra_svn all implement the same interface. And all three communicate with the Repository Layer—libsvn_ra_dav and libsvn_ra_svn do so across a network, and libsvn_ra_local connects to it directly. The libsvn_fs_base and libsvn_fs_fs libraries are another example of this.

The client itself also highlights modularity in the Subversion design. While Subversion itself comes with only a command-line client program, there are several third party programs which provide various forms of client GUI. These GUIs use the same APIs that the stock command-line client does. Subversion's libsvn_client library is the one-stop shop for most of the functionality necessary for designing a working Subversion client (see «Client Layer»).

Repository Layer


When referring to Subversion's Repository Layer, we're generally talking about two libraries—the repository library, and the filesystem library. These libraries provide the storage and reporting mechanisms for the various revisions of your version-controlled data. This layer is connected to the Client Layer via the Repository Access Layer, and is, from the perspective of the Subversion user, the stuff at the «other end of the line.»

The Subversion Filesystem is accessed via the libsvn_fs API, and is not a kernel-level filesystem that one would install in an operating system (like the Linux ext2 or NTFS), but a virtual filesystem. Rather than storing «files» and «directories» as real files and directories (as in, the kind you can navigate through using your favorite shell program), it uses one of two available abstract storage backends—either a Berkeley DB database environment, or a flat-file representation. (To learn more about the two repository back-ends, see «Repository Data Stores».) However, there has been considerable interest by the development community in giving future releases of Subversion the ability to use other back-end database systems, perhaps through a mechanism such as Open Database Connectivity (ODBC).

The filesystem API exported by libsvn_fs contains the kinds of functionality you would expect from any other filesystem API: you can create and remove files and directories, copy and move them around, modify file contents, and so on. It also has features that are not quite as common, such as the ability to add, modify, and remove metadata («properties») on each file or directory. Furthermore, the Subversion Filesystem is a versioning filesystem, which means that as you make changes to your directory tree, Subversion remembers what your tree looked like before those changes. And before the previous changes. And the previous ones. And so on, all the way back through versioning time to (and just beyond) the moment you first started adding things to the filesystem.

All the modifications you make to your tree are done within the context of a Subversion transaction. The following is a simplified general routine for modifying your filesystem:



  1. Begin a Subversion transaction.

  2. Make your changes (adds, deletes, property modifications, etc.).

  3. Commit your transaction.

Once you have committed your transaction, your filesystem modifications are permanently stored as historical artifacts. Each of these cycles generates a single new revision of your tree, and each revision is forever accessible as an immutable snapshot of «the way things were.»

The Transaction Distraction

The notion of a Subversion transaction, especially given its close proximity to the database code in libsvn_fs, can become easily confused with the transaction support provided by the underlying database itself. Both types of transaction exist to provide atomicity and isolation. In other words, transactions give you the ability to perform a set of actions in an «all or nothing» fashion—either all the actions in the set complete with success, or they all get treated as if none of them ever happened—and in a way that does not interfere with other processes acting on the data.

Database transactions generally encompass small operations related specifically to the modification of data in the database itself (such as changing the contents of a table row). Subversion transactions are larger in scope, encompassing higher-level operations like making modifications to a set of files and directories which are intended to be stored as the next revision of the filesystem tree. If that isn't confusing enough, consider this: Subversion uses a database transaction during the creation of a Subversion transaction (so that if the creation of Subversion transaction fails, the database will look as if we had never attempted that creation in the first place)!

Fortunately for users of the filesystem API, the transaction support provided by the database system itself is hidden almost entirely from view (as should be expected from a properly modularized library scheme). It is only when you start digging into the implementation of the filesystem itself that such things become visible (or interesting).

Most of the functionality provided by the filesystem interface comes as an action that occurs on a filesystem path. That is, from outside of the filesystem, the primary mechanism for describing and accessing the individual revisions of files and directories comes through the use of path strings like /foo/bar, just as if you were addressing files and directories through your favorite shell program. You add new files and directories by passing their paths-to-be to the right API functions. You query for information about them by the same mechanism.

Unlike most filesystems, though, a path alone is not enough information to identify a file or directory in Subversion. Think of a directory tree as a two-dimensional system, where a node's siblings represent a sort of left-and-right motion, and descending into subdirectories a downward motion. Рисунок 8.1, «Files and directories in two dimensions» shows a typical representation of a tree as exactly that.



Рисунок 8.1. Files and directories in two dimensions

Of course, the Subversion filesystem has a nifty third dimension that most filesystems do not have—Time! [47] In the filesystem interface, nearly every function that has a path argument also expects a root argument. This svn_fs_root_t argument describes either a revision or a Subversion transaction (which is usually just a revision-to-be), and provides that third-dimensional context needed to understand the difference between /foo/bar in revision 32, and the same path as it exists in revision 98. Рисунок 8.2, «Versioning time—the third dimension!» shows revision history as an added dimension to the Subversion filesystem universe.



Рисунок 8.2. Versioning time—the third dimension!

As we mentioned earlier, the libsvn_fs API looks and feels like any other filesystem, except that it has this wonderful versioning capability. It was designed to be usable by any program interested in a versioning filesystem. Not coincidentally, Subversion itself is interested in that functionality. But while the filesystem API should be sufficient for basic file and directory versioning support, Subversion wants more—and that is where libsvn_repos comes in.

The Subversion repository library (libsvn_repos) is basically a wrapper library around the filesystem functionality. This library is responsible for creating the repository layout, making sure that the underlying filesystem is initialized, and so on. Libsvn_repos also implements a set of hooks—scripts that are executed by the repository code when certain actions take place. These scripts are useful for notification, authorization, or whatever purposes the repository administrator desires. This type of functionality, and other utilities provided by the repository library, are not strictly related to implementing a versioning filesystem, which is why it was placed into its own library.

Developers who wish to use the libsvn_repos API will find that it is not a complete wrapper around the filesystem interface. That is, only certain major events in the general cycle of filesystem activity are wrapped by the repository interface. Some of these include the creation and commit of Subversion transactions, and the modification of revision properties. These particular events are wrapped by the repository layer because they have hooks associated with them. In the future, other events may be wrapped by the repository API. All of the remaining filesystem interaction will continue to occur directly via the libsvn_fs API, though.

For example, here is a code segment that illustrates the use of both the repository and filesystem interfaces to create a new revision of the filesystem in which a directory is added. Note that in this example (and all others throughout this book), the SVN_ERR() macro simply checks for a non-successful error return from the function it wraps, and returns that error if it exists.

Пример 8.1. Using the Repository Layer

/* Create a new directory at the path NEW_DIRECTORY in the Subversion

repository located at REPOS_PATH. Perform all memory allocation in

POOL. This function will create a new revision for the addition of

NEW_DIRECTORY. */

static svn_error_t *

make_new_directory (const char *repos_path,

const char *new_directory,

apr_pool_t *pool)

{

svn_error_t *err;



svn_repos_t *repos;

svn_fs_t *fs;

svn_revnum_t youngest_rev;

svn_fs_txn_t *txn;

svn_fs_root_t *txn_root;

const char *conflict_str;


/* Open the repository located at REPOS_PATH. */

SVN_ERR (svn_repos_open (&repos, repos_path, pool));


/* Get a pointer to the filesystem object that is stored in

REPOS. */

fs = svn_repos_fs (repos);
/* Ask the filesystem to tell us the youngest revision that

currently exists. */

SVN_ERR (svn_fs_youngest_rev (&youngest_rev, fs, pool));
/* Begin a new transaction that is based on YOUNGEST_REV. We are

less likely to have our later commit rejected as conflicting if we

always try to make our changes against a copy of the latest snapshot

of the filesystem tree. */

SVN_ERR (svn_fs_begin_txn (&txn, fs, youngest_rev, pool));
/* Now that we have started a new Subversion transaction, get a root

object that represents that transaction. */

SVN_ERR (svn_fs_txn_root (&txn_root, txn, pool));
/* Create our new directory under the transaction root, at the path

NEW_DIRECTORY. */

SVN_ERR (svn_fs_make_dir (txn_root, new_directory, pool));
/* Commit the transaction, creating a new revision of the filesystem

which includes our added directory path. */

err = svn_repos_fs_commit_txn (&conflict_str, repos,

&youngest_rev, txn, pool);

if (! err)

{

/* No error? Excellent! Print a brief report of our success. */



printf ("Directory '%s' was successfully added as new revision "

"'%ld'.\n", new_directory, youngest_rev);

}

else if (err->apr_err == SVN_ERR_FS_CONFLICT)



{

/* Uh-oh. Our commit failed as the result of a conflict

(someone else seems to have made changes to the same area

of the filesystem that we tried to modify). Print an error

message. */

printf ("A conflict occurred at path '%s' while attempting "

"to add directory '%s' to the repository at '%s'.\n",

conflict_str, new_directory, repos_path);

}

else


{

/* Some other error has occurred. Print an error message. */

printf ("An error occurred while attempting to add directory '%s' "

"to the repository at '%s'.\n",



n

Достарыңызбен бөлісу:
1   ...   26   27   28   29   30   31   32   33   34




©dereksiz.org 2024
әкімшілігінің қараңыз

    Басты бет