versioncontrol_fakevcs.module

Tracking 5.x-2.x branch
  1. drupal
    1. 5 contributions/versioncontrol/versioncontrol_fakevcs/versioncontrol_fakevcs.module

FakeVCS backend for Version Control API - An example module illustrating how to write a VCS backend.

Copyright 2007, 2008 by Jakob Petsovits ("jpetso", http://drupal.org/user/56020)

Functions & methods

NameDescription
versioncontrol_fakevcs_accountImplementation of [versioncontrol_backend]_account(): Manage (insert, update or delete) additional FakeVCS user account data in the database.
versioncontrol_fakevcs_alter_repositoriesImplementation of [versioncontrol_backend]_alter_repositories(): Add VCS specific repository data into a $repository['[xxx]_specific'] array. By convention, this function only adds data in this specific element and doesn't modify other…
versioncontrol_fakevcs_export_accountsImplementation of [vcs_backend]_export_accounts(): Export accounts of a repository to text data that is suitable for copying to the version control system's accounts file.
versioncontrol_fakevcs_format_revision_identifierImplementation of [versioncontrol_backend]_format_revision_identifier(): Get the user-visible version of a commit identifier a.k.a. 'revision', as plaintext.
versioncontrol_fakevcs_get_directory_contentsImplementation of [versioncontrol_backend]_get_directory_contents(): Retrieve the set of files and directories that exist at a specified revision in the given directory inside the repository.
versioncontrol_fakevcs_get_file_annotationImplementation of [versioncontrol_backend]_get_file_annotation(): Retrieve an array where each element represents a single line of the given file in the specified commit, annotated with the committer who last modified that line. Note that annotations…
versioncontrol_fakevcs_get_file_copyImplementation of [versioncontrol_backend]_open_file_handle(): Retrieve a copy of the contents of a given item in the repository. (You won't get the original because repositories can often be remote.)
versioncontrol_fakevcs_get_itemImplementation of [vcs_backend]_get_item(): Try to retrieve a given item in a repository.
versioncontrol_fakevcs_get_selected_label_from_operationImplementation of [versioncontrol_backend]_get_selected_label_from_operation(): Retrieve the tag or branch that applied to that item during the given operation. The result of this function will be used for the selected label property of the item,…
versioncontrol_fakevcs_get_selected_label_from_other_itemImplementation of [versioncontrol_backend]_get_selected_label_from_other_item(): Retrieve a valid label (tag or branch) for a new @p $target_item that is (hopefully) similar or related to that of the given @p $other_item which already has a selected…
versioncontrol_fakevcs_import_accountsImplementation of [vcs_backend]_import_accounts(): Import accounts into a repository, given text data from the accounts file. No accounts are deleted, new accounts are inserted, and existing accounts are updated with imported ones.
versioncontrol_fakevcs_operationImplementation of [versioncontrol_backend]_operation(): Act on database changes when commit, tag or branch operations are inserted or deleted. Note that this hook is not necessarily called at the time when the operation actually happens - operations…
versioncontrol_fakevcs_repositoryImplementation of [versioncontrol_backend]_repository(): Manage (insert, update or delete) additional FakeVCS repository data in the database.
versioncontrol_fakevcs_versioncontrol_backendsImplementation of hook_versioncontrol_backends().
versioncontrol_get_parallel_itemsImplementation of [versioncontrol_backend]_get_parallel_items(): Given an item in a repository, retrieve related versions of that item on all different branches and/or tags where the item exists.

Constants

NameDescription
VERSIONCONTROL_FAKEVCS_UPDATE_CRON
VERSIONCONTROL_FAKEVCS_UPDATE_SCRIPT

File

View source
  1. <?php
  2. /**
  3. * @file
  4. * FakeVCS backend for Version Control API -
  5. * An example module illustrating how to write a VCS backend.
  6. *
  7. * Copyright 2007, 2008 by Jakob Petsovits ("jpetso", http://drupal.org/user/56020)
  8. */
  9. // Update methods.
  10. define('VERSIONCONTROL_FAKEVCS_UPDATE_CRON', 0);
  11. define('VERSIONCONTROL_FAKEVCS_UPDATE_SCRIPT', 1);
  12. // The admin pages.
  13. include_once(drupal_get_path('module', 'versioncontrol_fakevcs') .'/versioncontrol_fakevcs.admin.inc');
  14. /**
  15. * Implementation of hook_versioncontrol_backends().
  16. *
  17. * This function is mandatory for backends to implement.
  18. *
  19. * @return
  20. * A structured array containing information about this backend, wrapped
  21. * in a structured array. Array key is the unique string identifier of
  22. * the backend. The corresponding array values are again structured arrays
  23. * and consist of elements with the following keys:
  24. *
  25. * - 'name': The user-visible name of the VCS.
  26. * - 'description': A short description of the backend, if possible not
  27. * longer than one or two sentences.
  28. * - 'capabilities': An array listing optional capabilities, in addition to
  29. * the required functionality like retrieval of detailed commit
  30. * information. Array values can be an arbitrary combination
  31. * of VERSIONCONTROL_CAPABILITY_* values. If no additional capabilities
  32. * are supported by the backend, this array will be empty.
  33. * - 'flags': An array listing which tables should be managed by
  34. * Version Control API instead of doing it manually in the backend.
  35. * Array values can be an arbitrary combination of VERSIONCONTROL_FLAG_*
  36. * values. If no array additions should be automatically managed,
  37. * this array will be empty.
  38. */
  39. function versioncontrol_fakevcs_versioncontrol_backends() {
  40. // Our example VCS is called FakeVCS, and supports all possible capabilities.
  41. return array(
  42. // The array key is up to 8 characters long, and used as unique identifier
  43. // for this VCS, in functions, URLs and in the database.
  44. 'fakevcs' => array(
  45. // The user-visible name of the VCS.
  46. 'name' => 'FakeVCS',
  47. // A short description of the VCS, if possible not longer than one or two sentences.
  48. 'description' => t('FakeVCS is a version control system that is specifically capable in doing everything that any other version control system might ever do.'),
  49. // A list of optional capabilities, in addition to the required retrieval
  50. // of detailed commit information. All allowed values are listed below.
  51. 'capabilities' => array(
  52. // Able to cancel commits if the committer lacks permissions
  53. // to commit to specific paths and/or branches.
  54. VERSIONCONTROL_CAPABILITY_COMMIT_RESTRICTIONS,
  55. // Able to cancel branch or tag assignments if the committer lacks
  56. // permissions to create/update/delete those.
  57. VERSIONCONTROL_CAPABILITY_BRANCH_TAG_RESTRICTIONS,
  58. // Able to retrieve a file or its revision number based on a global
  59. // revision identifier.
  60. VERSIONCONTROL_CAPABILITY_ATOMIC_COMMITS,
  61. // The version control system assigns revisions not only to files
  62. // but also to directories.
  63. VERSIONCONTROL_CAPABILITY_DIRECTORY_REVISIONS,
  64. ),
  65. // An array listing which tables should be managed by Version Control API
  66. // instead of doing it manually in the backend.
  67. // All allowed values are listed below.
  68. 'flags' => array(
  69. // versioncontrol_insert_repository() will automatically insert
  70. // array elements from $repository['[xxx]_specific'] into
  71. // {versioncontrol_[xxx]_repositories} and versioncontrol_get_repositories()
  72. // will automatically fetch it from there.
  73. VERSIONCONTROL_FLAG_AUTOADD_REPOSITORIES,
  74. ),
  75. ),
  76. // More backend entries are possible - modules probably won't need this,
  77. // but let's still provide the opportunity to do so, for consistency
  78. // with similar hooks from other modules and easier merging of the arrays.
  79. );
  80. }
  81. /**
  82. * Implementation of [versioncontrol_backend]_alter_repositories():
  83. * Add VCS specific repository data into a $repository['[xxx]_specific'] array.
  84. * By convention, this function only adds data in this specific element
  85. * and doesn't modify other parts of the repository array.
  86. *
  87. * Also, this function is optional for backend modules to implement. If you
  88. * don't need custom additions to the repositories, just don't implement it.
  89. *
  90. * @param $repositories
  91. * The repositories for which this backend module needs to retrieve
  92. * additional repository data. This is an array like the one returned by
  93. * versioncontrol_get_repositories(), and even the '[xxx]_specific' arrays
  94. * already exist. (If the VERSIONCONTROL_FLAG_AUTOADD_REPOSITORIES flag
  95. * has been set by this module, it may even be filled with values already.)
  96. * @param $fakevcs_specific_constraints
  97. * An array of FakeVCS specific filter constraints which were passed to
  98. * versioncontrol_get_repositories(). Say, if FakeVCS supported modules like
  99. * the CVS ones, the array would maybe contain a 'modules' constraint
  100. * for filtering by module.
  101. */
  102. function versioncontrol_fakevcs_alter_repositories(&$repositories, $fakevcs_specific_constraints = array()) {
  103. foreach ($repositories as $repo_id => $repository) {
  104. // Retrieve our own custom stuff.
  105. $additions = array(
  106. 'modules' => array('drupal', 'contributions'),
  107. );
  108. // Filter out commits that don't match the given constraints.
  109. if (isset($fakevcs_specific_constraints['modules'])) {
  110. foreach ($fakevcs_specific_constraints['modules'] as $module_constraint) {
  111. if (!in_array($module_constraint, $additions['modules'])) {
  112. unset($repositories[$repo_id]);
  113. continue;
  114. }
  115. }
  116. }
  117. // Merge the additions into the existing commit array.
  118. $repositories[$repo_id]['fakevcs_specific'] = array_merge(
  119. $repository['fakevcs_specific'], $additions
  120. );
  121. }
  122. }
  123. /**
  124. * Implementation of [versioncontrol_backend]_format_revision_identifier():
  125. * Get the user-visible version of a commit identifier a.k.a. 'revision',
  126. * as plaintext.
  127. *
  128. * Version control backends can choose to implement their own version of this
  129. * function, which for example makes it possible to cut the SHA-1 hash in
  130. * distributed version control systems down to a readable length.
  131. *
  132. * @param $operation
  133. * The operation whose commit identifier should be themed.
  134. * @param $format
  135. * Either 'full' for the original version, or 'short' for a more compact form.
  136. * If the commit identifier doesn't need to be shortened, the results can
  137. * be the same for both versions.
  138. */
  139. function versioncontrol_fakevcs_format_revision_identifier($operation, $format = 'full') {
  140. switch ($format) {
  141. case 'full':
  142. case 'short':
  143. default:
  144. // Suppose we're a distributed VCS backend and have an SHA-1 hash:
  145. // $operation['revision'] == '30581e4ec3347d1294ec05a91eec1a8588e5993c'
  146. // Let's return only the first 12 characters of the revision identifier,
  147. // like Mercurial (including hgweb) does by default.
  148. return substr($operation['revision'], 0, 12);
  149. // SVN also wants to format revisions in a slightly custom way:
  150. return 'r'. $operation['revision'];
  151. }
  152. }
  153. /**
  154. * Implementation of [versioncontrol_backend]_get_selected_label_from_operation():
  155. * Retrieve the tag or branch that applied to that item during the given
  156. * operation. The result of this function will be used for the selected label
  157. * property of the item, which is necessary to preserve the item state
  158. * throughout navigational API functions.
  159. *
  160. * This function is mandatory for backends to implement.
  161. *
  162. * @param $operation
  163. * A single operation array to which the item belongs, like the ones returned
  164. * by versioncontrol_get_operations(). Specifically, $operation contains the
  165. * 'labels' element which should probably be reused by this function.
  166. * @param $target_item
  167. * The item revision for which the label should be retrieved.
  168. *
  169. * @return
  170. * NULL if the given item does not belong to any label or if the appropriate
  171. * label cannot be retrieved. Otherwise a label array is returned, consisting
  172. * of the following elements:
  173. *
  174. * - 'name': The branch or tag name (a string).
  175. * - 'type': Whether this label is a branch (indicated by the
  176. * VERSIONCONTROL_OPERATION_BRANCH constant) or a tag
  177. * (VERSIONCONTROL_OPERATION_TAG).
  178. *
  179. * In case the label array also contains the 'label_id' element (which
  180. * happens when it's copied from the $operation['labels'] array) there will
  181. * be a small performance improvement as the label doesn't need to be
  182. * compared to and loaded from the database anymore.
  183. */
  184. function versioncontrol_fakevcs_get_selected_label_from_operation($operation, $target_item) {
  185. // How CVS and many other version control systems will probably do it,
  186. // as they have exactly one label assigned to each operation.
  187. return $operation['labels'][0];
  188. // If an operation - or more specifically, a commit - applies to multiple
  189. // branches and/or tags (as can happen in SVN, for example), then the correct
  190. // label for each item has to be determined.
  191. }
  192. /**
  193. * Implementation of [versioncontrol_backend]_get_selected_label_from_other_item():
  194. * Retrieve a valid label (tag or branch) for a new @p $target_item that is
  195. * (hopefully) similar or related to that of the given @p $other_item which
  196. * already has a selected label assigned. If the backend cannot find a related
  197. * label, return any valid label. The result of this function will be used for
  198. * the selected label property of each item, which is necessary to preserve the
  199. * item state throughout navigational API functions.
  200. *
  201. * This function is mandatory for backends to implement.
  202. *
  203. * @param $repository
  204. * The repository array (like returned by versioncontrol_get_repository())
  205. * of the repository which contains both the source and the successor item.
  206. * @param $target_item
  207. * The item revision for which the label should be retrieved.
  208. * @param $other_item
  209. * The item revision that the selected label should be derived from.
  210. * For example, if @p $other_item in a CVS repository is at revision
  211. * '1.5.2.1' which is on the 'DRUPAL-6--1' branch, and the @p $target_item
  212. * is at revision '1.5' (its predecessor) which is present on both the
  213. * 'DRUPAL-6--1' and 'HEAD' branches, then this function should return a
  214. * label array for the 'DRUPAL-6--1' branch.
  215. * @param $other_item_tags
  216. * An array with a simple list of strings that describe properties of the
  217. * @p $other_item, in relation to the @p $target_item. You can use those
  218. * in order to make assumptions so that the selected label can be retrieved
  219. * more accurately or with better performance. Version Control API passes a
  220. * list that may contain zero or more of the following tags:
  221. *
  222. * - 'source_item': The @p $other_item is a predecessor of the
  223. * @p $target_item - same entity, but in an earlier revision and
  224. * potentially with a different path, too (only if the backend supports
  225. * item moves).
  226. * - 'successor_item': The @p $other_item is a successor of the
  227. * @p $target_item - same entity, but in a later revision and
  228. * potentially with a different path, too (only if the backend supports
  229. * item moves).
  230. * - 'same_revision': The @p $other_item is at the same (global) revision
  231. * as the @p $target_item. Specifically meant for backends whose
  232. * version control systems don't support atomic commits.
  233. *
  234. * @return
  235. * NULL if the given item does not belong to any label or if an appropriate
  236. * label cannot be retrieved. Otherwise a label array is returned, consisting
  237. * of the following elements:
  238. *
  239. * - 'name': The branch or tag name (a string).
  240. * - 'type': Whether this label is a branch (indicated by the
  241. * VERSIONCONTROL_OPERATION_BRANCH constant) or a tag
  242. * (VERSIONCONTROL_OPERATION_TAG).
  243. *
  244. * In case the label array also contains the 'label_id' element (which
  245. * happens when it's copied from the $operation['labels'] array) there will
  246. * be a small performance improvement as the label doesn't need to be
  247. * compared to and loaded from the database anymore.
  248. */
  249. function versioncontrol_fakevcs_get_selected_label_from_other_item($repository, $target_item, &$other_item, $other_item_tags = array()) {
  250. // First up, optimizations - maybe we can do without the generic
  251. // "label transfer" code from further down and use assumptions instead.
  252. // Let's assume for FakeVCS repositories that if an item wears a label, then
  253. // an item at another path but with the same (file-level) revision can also
  254. // wear that same label. That is the case with some version control systems
  255. // (e.g. Git, Mercurial, Bazaar) but might not be the case with others
  256. // (CVS for its lack of global revision identifiers, SVN for its use of
  257. // directory structure as tag/branch identifiers).
  258. if ($item['revision'] == $other_item['revision']) {
  259. return versioncontrol_get_item_selected_label($repository, $other_item);
  260. }
  261. // If the $other_item is a successor item on a branch, some version control
  262. // systems (like CVS) can guarantee that the $target_item, the predecessor,
  263. // is always on the same branch. So no need for database queries, yay.
  264. if (in_array('successor_item', $other_item_tags)) {
  265. $label = versioncontrol_get_item_selected_label($repository, $other_item);
  266. if (isset($label['type']) && $label['type'] == VERSIONCONTROL_OPERATION_BRANCH) {
  267. return $label;
  268. }
  269. }
  270. // Otherwise we might not be able to derive the $target_item's label,
  271. // in which case we need to fall back to the database or a VCS invocation.
  272. // For example, something like this.
  273. if (versioncontrol_fetch_item_revision_id($repository, $target_item)) {
  274. $constraints = array(
  275. 'item_revision_id' => array($target_item['item_revision_id']),
  276. );
  277. $commit_operations = versioncontrol_get_commit_operations($constraints);
  278. if (!empty($commit_operations)) { // yo, found the associated commit!
  279. // Code taken from the CVS backend, which only assigns a single branch
  280. // to any given commit operation, so it can just take the first one.
  281. $commit_operation = reset($commit_operations); // first (only) element
  282. return $commit_operation['labels'][0];
  283. }
  284. }
  285. // (You can even do more attempts if you want to, like trying to ask
  286. // the VCS itself. Or maybe not, depends on your motivation and the
  287. // VCS's capabilities.)
  288. // No label could be retrieved by looking at the other item, sorry.
  289. return NULL;
  290. }
  291. /**
  292. * Implementation of [vcs_backend]_get_item():
  293. * Try to retrieve a given item in a repository.
  294. *
  295. * This function is optional for VCS backends to implement, be sure to check
  296. * with versioncontrol_backend_implements($repository['vcs'], 'get_item')
  297. * if the particular backend actually implements it.
  298. *
  299. * @param $repository
  300. * The repository that the item is located in.
  301. * @param $path
  302. * The path of the requested item.
  303. * @param $revision
  304. * A specific revision for the requested item (as interpreted by the
  305. * VCS backend), or NULL if any revision is good enough - preferably,
  306. * the most recent one.
  307. *
  308. * @return
  309. * If the item with the given path and revision cannot be retrieved, NULL is
  310. * returned. Otherwise the result of the backend function is a structured
  311. * array with the elements 'item' and 'selected_label', making up the whole
  312. * picture.
  313. *
  314. * - 'item': An item array, consisting of the following elements:
  315. *
  316. * - 'type': Specifies the item type, which is either
  317. * VERSIONCONTROL_ITEM_FILE or VERSIONCONTROL_ITEM_DIRECTORY for
  318. * items that still exist, or VERSIONCONTROL_ITEM_FILE_DELETED
  319. * respectively VERSIONCONTROL_ITEM_DIRECTORY_DELETED for items
  320. * that have been removed.
  321. * - 'path': The path of the item at the specific revision.
  322. * - 'revision': The currently selected (file-level) revision of the
  323. * item. If there is no such revision (which may be the case for
  324. * directory items) then the 'revision' element is an empty string.
  325. *
  326. * If the returned item is already present in the database, the
  327. * 'item_revision_id' database identifier might also be filled in
  328. * (optional, depends on the VCS backend).
  329. *
  330. * - 'selected_label':
  331. * In case no branch or tag applies to that item or could not be
  332. * retrieved for whatever reasons, the selected label can also be NULL.
  333. * Otherwise, it's a label array describing the selected label, with the
  334. * following keys:
  335. *
  336. * - 'name': The branch or tag name (a string).
  337. * - 'type': Whether this label is a branch (indicated by the
  338. * VERSIONCONTROL_OPERATION_BRANCH constant) or a tag
  339. * (VERSIONCONTROL_OPERATION_TAG).
  340. *
  341. * In case the label array also contains the 'label_id' element (which
  342. * happens when it's copied from the $operation['labels'] array) there
  343. * will be a small performance improvement as the label doesn't need to
  344. * be compared to and loaded from the database anymore.
  345. */
  346. function versioncontrol_fakevcs_get_item($repository, $path, $revision = '') {
  347. // Slightly adapted version of the SVN backend's implementation.
  348. if (empty($revision)) {
  349. $revision = 'HEAD';
  350. }
  351. // Wherever you get your item info from.
  352. $info = fakevcs_item_info($repository, $path, $revision);
  353. $item = array(
  354. 'path' => $path,
  355. 'revision' => $info['rev'],
  356. 'type' => ($info['rev'] == 'dir')
  357. ? VERSIONCONTROL_ITEM_DIRECTORY
  358. : VERSIONCONTROL_ITEM_FILE,
  359. );
  360. return array('item' => $item, 'selected_label' => NULL);
  361. }
  362. /**
  363. * Implementation of [versioncontrol_backend]_get_parallel_items():
  364. * Given an item in a repository, retrieve related versions of that item on all
  365. * different branches and/or tags where the item exists.
  366. *
  367. * This function is optional for VCS backends to implement, be sure to check
  368. * with versioncontrol_backend_implements($repository['vcs'], 'get_directory_contents')
  369. * if the particular backend actually implements it.
  370. *
  371. * @param $repository
  372. * The repository that the item is located in.
  373. * @param $item
  374. * The item whose parallel sibling should be retrieved.
  375. * @param $label_type
  376. * If unset, siblings will be retrieved both on branches and tags.
  377. * If set to VERSIONCONTROL_OPERATION_BRANCH or VERSIONCONTROL_OPERATION_TAG,
  378. * results are limited to just that label type.
  379. *
  380. * @return
  381. * A structured item array of parallel items on all branches and tags,
  382. * possibly including the original item itself (if appropriate for the given
  383. * @p $label_type). Array keys do not convey any specific meaning, the
  384. * corresponding values are again structured arrays, each with a pair of
  385. * 'item' and 'selected_label' elements as follows.
  386. *
  387. * - 'item': An item array, consisting of the following elements:
  388. *
  389. * - 'type': Specifies the item type, which is either
  390. * VERSIONCONTROL_ITEM_FILE or VERSIONCONTROL_ITEM_DIRECTORY for
  391. * items that still exist, or VERSIONCONTROL_ITEM_FILE_DELETED
  392. * respectively VERSIONCONTROL_ITEM_DIRECTORY_DELETED for items
  393. * that have been removed.
  394. * - 'path': The path of the item at the specific revision.
  395. * - 'revision': The currently selected (file-level) revision of the
  396. * item. If there is no such revision (which may be the case for
  397. * directory items) then the 'revision' element is an empty string.
  398. *
  399. * If the returned item is already present in the database, the
  400. * 'item_revision_id' database identifier might also be filled in
  401. * (optional, depends on the VCS backend).
  402. *
  403. * - 'selected_label':
  404. * A label array describing the selected label, with the following keys:
  405. *
  406. * - 'name': The branch or tag name (a string).
  407. * - 'type': Whether this label is a branch (indicated by the
  408. * VERSIONCONTROL_OPERATION_BRANCH constant) or a tag
  409. * (VERSIONCONTROL_OPERATION_TAG).
  410. * - 'label_id': Optional. The label identifier (a simple integer), used
  411. * for unique identification of branches and tags in the database.
  412. *
  413. * NULL is returned if the given item is not inside the repository,
  414. * or has not been inside the repository at the specified revision.
  415. * An empty array is returned if the item is valid, but no parallel sibling
  416. * items can be found for the given @p $label_type.
  417. */
  418. function versioncontrol_get_parallel_items($repository, $item, $label_type = NULL) {
  419. // How CVS would probably do it, if for example
  420. // $item['path'] == '/contributions/modules/versioncontrol/versioncontrol.module':
  421. return array(
  422. array(
  423. 'item' => array(
  424. 'type' => VERSIONCONTROL_ITEM_FILE,
  425. 'path' => '/contributions/modules/versioncontrol/versioncontrol.module',
  426. 'revision' => '1.23',
  427. ),
  428. 'selected_label' => array(
  429. 'name' => 'HEAD',
  430. 'type' => VERSIONCONTROL_OPERATION_BRANCH,
  431. ),
  432. ),
  433. array(
  434. 'item' => array(
  435. 'type' => VERSIONCONTROL_ITEM_FILE,
  436. 'path' => '/contributions/modules/versioncontrol/versioncontrol.module',
  437. 'revision' => '1.23.2.42',
  438. ),
  439. 'selected_label' => array(
  440. 'name' => 'DRUPAL-5--1',
  441. 'type' => VERSIONCONTROL_OPERATION_BRANCH,
  442. ),
  443. ),
  444. array(
  445. 'item' => array(
  446. 'type' => VERSIONCONTROL_ITEM_FILE,
  447. 'path' => '/contributions/modules/versioncontrol/versioncontrol.module',
  448. 'revision' => '1.23.2.42',
  449. ),
  450. 'selected_label' => array(
  451. 'name' => 'DRUPAL-5--1-2',
  452. 'type' => VERSIONCONTROL_OPERATION_TAG,
  453. ),
  454. ),
  455. );
  456. // How SVN could also do it, if for example
  457. // $item['path'] == '/trunk/contributions/modules/versioncontrol':
  458. return array(
  459. array(
  460. 'item' => array(
  461. 'type' => VERSIONCONTROL_ITEM_DIRECTORY,
  462. 'path' => '/trunk/contributions/modules/versioncontrol',
  463. 'revision' => '23',
  464. ),
  465. 'selected_label' => array(
  466. 'name' => 'trunk',
  467. 'type' => VERSIONCONTROL_OPERATION_BRANCH,
  468. ),
  469. ),
  470. array(
  471. 'item' => array(
  472. 'type' => VERSIONCONTROL_ITEM_DIRECTORY,
  473. 'path' => '/branches/5.x-1.x/contributions/modules/versioncontrol',
  474. 'revision' => '42',
  475. ),
  476. 'selected_label' => array(
  477. 'name' => '5.x-1.x',
  478. 'type' => VERSIONCONTROL_OPERATION_BRANCH,
  479. ),
  480. ),
  481. );
  482. }
  483. /**
  484. * Implementation of [versioncontrol_backend]_get_directory_contents():
  485. * Retrieve the set of files and directories that exist at a specified revision
  486. * in the given directory inside the repository.
  487. *
  488. * This function is optional for VCS backends to implement, be sure to check
  489. * with versioncontrol_backend_implements($repository['vcs'], 'get_directory_contents')
  490. * if the particular backend actually implements it.
  491. *
  492. * @param $repository
  493. * The repository that the directory item is located in.
  494. * @param $directory_item
  495. * The parent item of the the items that should be listed.
  496. * @param $recursive
  497. * If FALSE, only the direct children of $path will be retrieved.
  498. * If TRUE, you'll get every single descendant of $path.
  499. *
  500. * @return
  501. * A structured item array of items that have been inside the directory in
  502. * its given state, including the directory item itself. Array keys are the
  503. * current/new paths. The corresponding values are again structured arrays,
  504. * each with a pair of 'item' and 'selected_label' elements as follows.
  505. *
  506. * - 'item': An item array, consisting of the following elements:
  507. *
  508. * - 'type': Specifies the item type, which is either
  509. * VERSIONCONTROL_ITEM_FILE or VERSIONCONTROL_ITEM_DIRECTORY for
  510. * items that still exist, or VERSIONCONTROL_ITEM_FILE_DELETED
  511. * respectively VERSIONCONTROL_ITEM_DIRECTORY_DELETED for items
  512. * that have been removed.
  513. * - 'path': The path of the item at the specific revision.
  514. * - 'revision': The currently selected (file-level) revision of the
  515. * item. If there is no such revision (which may be the case for
  516. * directory items) then the 'revision' element is an empty string.
  517. *
  518. * If the returned item is already present in the database, the
  519. * 'item_revision_id' database identifier might also be filled in
  520. * (optional, depends on the VCS backend).
  521. *
  522. * - 'selected_label':
  523. * In case no branch or tag applies to that item or could not be
  524. * retrieved for whatever reasons, the selected label can also be NULL.
  525. * Otherwise, it's a label array describing the selected label, with the
  526. * following keys:
  527. *
  528. * - 'name': The branch or tag name (a string).
  529. * - 'type': Whether this label is a branch (indicated by the
  530. * VERSIONCONTROL_OPERATION_BRANCH constant) or a tag
  531. * (VERSIONCONTROL_OPERATION_TAG).
  532. *
  533. * NULL is returned if the given item is not under version control,
  534. * or was not under version control at the time of the given revision.
  535. * The API module ensures that the passed item is a directory item.
  536. */
  537. function versioncontrol_fakevcs_get_directory_contents($repository, $directory_item, $recursive = FALSE) {
  538. // Assuming $parent_item is an item array that looks like this:
  539. $directory_item = array(
  540. 'type' => VERSIONCONTROL_ITEM_DIRECTORY,
  541. 'path' => '/trunk/contributions/modules/versioncontrol',
  542. 'revision' => '666',
  543. );
  544. // $repository is some SVN repository and $recursive == FALSE. SVN without
  545. // branch/tag emulation can return NULL for all the selected labels.
  546. return array(
  547. '/trunk/contributions/modules/versioncontrol' => array(
  548. 'item' => array( // == rtrim($path, '/')
  549. 'type' => VERSIONCONTROL_ITEM_DIRECTORY,
  550. 'path' => '/trunk/contributions/modules/versioncontrol',
  551. 'revision' => '502',
  552. ),
  553. 'selected_label' => NULL,
  554. )
  555. '/trunk/contributions/modules/versioncontrol/versioncontrol.module' => array(
  556. 'item' => array(
  557. 'type' => VERSIONCONTROL_ITEM_FILE,
  558. 'path' => '/trunk/contributions/modules/versioncontrol/versioncontrol.module',
  559. 'revision' => '502',
  560. ),
  561. 'selected_label' => NULL,
  562. ),
  563. '/trunk/contributions/modules/versioncontrol/versioncontrol.info' => array(
  564. 'item' => array(
  565. 'type' => VERSIONCONTROL_ITEM_FILE,
  566. 'path' => '/trunk/contributions/modules/versioncontrol/versioncontrol.info',
  567. 'revision' => '404',
  568. ),
  569. 'selected_label' => NULL,
  570. ),
  571. '/trunk/contributions/modules/versioncontrol/versioncontrol.install' => array(
  572. 'item' => array(
  573. 'type' => VERSIONCONTROL_ITEM_FILE,
  574. 'path' => '/trunk/contributions/modules/versioncontrol/versioncontrol.install',
  575. 'revision' => '404',
  576. ),
  577. 'selected_label' => NULL,
  578. ),
  579. '/trunk/contributions/modules/versioncontrol/README.txt' => array(
  580. 'item' => array(
  581. 'type' => VERSIONCONTROL_ITEM_FILE,
  582. 'path' => '/trunk/contributions/modules/versioncontrol/README.txt',
  583. 'revision' => '404',
  584. ),
  585. 'selected_label' => NULL,
  586. ),
  587. '/trunk/contributions/modules/versioncontrol/versioncontrol_fakevcs' => array(
  588. 'item' => array(
  589. 'type' => VERSIONCONTROL_ITEM_DIRECTORY,
  590. 'path' => '/trunk/contributions/modules/versioncontrol/versioncontrol_fakevcs.txt',
  591. 'revision' => '497',
  592. ),
  593. 'selected_label' => NULL,
  594. ),
  595. );
  596. // Or the same thing in CVS - note that 'revision' is an empty string
  597. // for directories, as CVS doesn't support versioned directories.
  598. $directory_item = array(
  599. 'type' => VERSIONCONTROL_ITEM_DIRECTORY,
  600. 'path' => '/contributions/modules/versioncontrol',
  601. 'revision' => '',
  602. );
  603. // $repository is some CVS repository and $recursive == TRUE.
  604. // For the purpose of example, we use the same label as the directory item.
  605. // (Real-life usage might or might not require more correctness checks.)
  606. $selected_label = versioncontrol_get_selected_label($directory_item);
  607. return array(
  608. '/contributions/modules/versioncontrol' => array(
  609. 'item' => array( // == rtrim($path, '/')
  610. 'type' => VERSIONCONTROL_ITEM_DIRECTORY,
  611. 'path' => '/contributions/modules/versioncontrol',
  612. 'revision' => '', // CVS doesn't track directory-level revisions
  613. ),
  614. 'selected_label' => $selected_label,
  615. ),
  616. '/contributions/modules/versioncontrol/versioncontrol.module' => array(
  617. 'item' => array(
  618. 'type' => VERSIONCONTROL_ITEM_FILE,
  619. 'path' => '/contributions/modules/versioncontrol/versioncontrol.module',
  620. 'revision' => '1.19',
  621. ),
  622. 'selected_label' => $selected_label,
  623. ),
  624. '/contributions/modules/versioncontrol/versioncontrol.info' => array(
  625. 'item' => array(
  626. 'type' => VERSIONCONTROL_ITEM_FILE,
  627. 'path' => '/contributions/modules/versioncontrol/versioncontrol.info',
  628. 'revision' => '1.1',
  629. ),
  630. 'selected_label' => $selected_label,
  631. ),
  632. '/contributions/modules/versioncontrol/versioncontrol.install' => array(
  633. 'item' => array(
  634. 'type' => VERSIONCONTROL_ITEM_FILE,
  635. 'path' => '/contributions/modules/versioncontrol/versioncontrol.install',
  636. 'revision' => '1.5',
  637. ),
  638. 'selected_label' => $selected_label,
  639. ),
  640. '/contributions/modules/versioncontrol/README.txt' => array(
  641. 'item' => array(
  642. 'type' => VERSIONCONTROL_ITEM_FILE,
  643. 'path' => '/contributions/modules/versioncontrol/README.txt',
  644. 'revision' => '1.1',
  645. ),
  646. 'selected_label' => $selected_label,
  647. ),
  648. '/contributions/modules/versioncontrol/fakevcs_backend' => array(
  649. 'item' => array(
  650. 'type' => VERSIONCONTROL_ITEM_DIRECTORY,
  651. 'path' => '/contributions/modules/versioncontrol/fakevcs_backend',
  652. 'revision' => '',
  653. ),
  654. 'selected_label' => $selected_label,
  655. ),
  656. '/contributions/modules/versioncontrol/fakevcs_backend/fakevcs_backend.module' => array(
  657. 'item' => array(
  658. 'type' => VERSIONCONTROL_ITEM_FILE_DELETED, // only for non-atomic-commit VCSs (= CVS)
  659. 'path' => '/contributions/modules/versioncontrol/fakevcs_backend/fakevcs_backend.module',
  660. 'revision' => '1.11', // last existing version
  661. ),
  662. 'selected_label' => $selected_label,
  663. ),
  664. '/contributions/modules/versioncontrol/versioncontrol_fakevcs' => array(
  665. 'item' => array(
  666. 'type' => VERSIONCONTROL_ITEM_DIRECTORY,
  667. 'path' => '/contributions/modules/versioncontrol/versioncontrol_fakevcs',
  668. 'revision' => '',
  669. ),
  670. 'selected_label' => $selected_label,
  671. ),
  672. '/contributions/modules/versioncontrol/versioncontrol_fakevcs/versioncontrol_fakevcs.module' => array(
  673. 'item' => array(
  674. 'type' => VERSIONCONTROL_ITEM_FILE,
  675. 'path' => '/contributions/modules/versioncontrol/versioncontrol_fakevcs/versioncontrol_fakevcs.module',
  676. 'revision' => '1.2',
  677. ),
  678. 'selected_label' => $selected_label,
  679. ),
  680. );
  681. }
  682. /**
  683. * Implementation of [versioncontrol_backend]_open_file_handle():
  684. * Retrieve a copy of the contents of a given item in the repository.
  685. * (You won't get the original because repositories can often be remote.)
  686. *
  687. * If a file could not be created, backends should take care to delete any
  688. * remaining temporary files before returning.
  689. *
  690. * This function is optional for VCS backends to implement, be sure to check
  691. * with versioncontrol_backend_implements($repository['vcs'], 'get_file_copy')
  692. * if the particular backend actually implements it.
  693. *
  694. * @param $repository
  695. * The repository that the file item is located in.
  696. * @param $file_item
  697. * The file item whose contents should be retrieved.
  698. * @param $destination
  699. * The path where the copied file should be written to.
  700. *
  701. * @return
  702. * TRUE if the file was successfully created, FALSE if not.
  703. * The API module ensures that the passed item is a file item.
  704. */
  705. function versioncontrol_fakevcs_get_file_copy($repository, $file_item, $destination) {
  706. exec('fakevcs cat '. $repository['root'] . $file_item['path'] .' > '. $destination,
  707. $output, $return_code);
  708. if ($return_code != 0) {
  709. @unlink($destination);
  710. return FALSE;
  711. }
  712. return TRUE;
  713. }
  714. /**
  715. * Implementation of [versioncontrol_backend]_get_file_annotation():
  716. * Retrieve an array where each element represents a single line of the
  717. * given file in the specified commit, annotated with the committer who last
  718. * modified that line. Note that annotations are generally a quite slow
  719. * operation, so expect this function to take a bit more time as well.
  720. *
  721. * This function is optional for VCS backends to implement, be sure to check
  722. * with versioncontrol_backend_implements($repository['vcs'], 'get_file_annotation')
  723. * if the particular backend actually implements it.
  724. *
  725. * @param $repository
  726. * The repository that the file item is located in.
  727. * @param $file_item
  728. * The file item whose annotation should be retrieved.
  729. *
  730. * @return
  731. * A structured array that consists of one element per line, with
  732. * line numbers as keys (starting from 1) and a structured array as values,
  733. * where each of them consists of elements with the following keys:
  734. *
  735. * - 'username': The system specific VCS username of the last committer.
  736. * - 'line': The contents of the line, without linebreak characters.
  737. *
  738. * NULL is returned if the given item is not under version control,
  739. * or was not under version control at the time of the given revision,
  740. * or if it is marked as binary file.
  741. * The API module ensures that the passed item is a file item.
  742. */
  743. function versioncontrol_fakevcs_get_file_annotation($repository, $file_item) {
  744. // In case the file is marked as text file:
  745. return array(
  746. 1 => array(
  747. 'username' => 'dries',
  748. 'line' => '<?php',
  749. ),
  750. 2 => array(
  751. 'username' => 'jpetso',
  752. 'line' => '// $Id$',
  753. ),
  754. );
  755. }
  756. /**
  757. * Implementation of [versioncontrol_backend]_operation():
  758. * Act on database changes when commit, tag or branch operations are inserted
  759. * or deleted. Note that this hook is not necessarily called at the time
  760. * when the operation actually happens - operations can also be inserted
  761. * by a cron script when the actual commit/branch/tag has been accomplished
  762. * for quite a while already.
  763. *
  764. * This function is optional for backend modules to implement. If you don't
  765. * need custom operation data, just don't implement it.
  766. *
  767. * @param $op
  768. * 'insert' when the operation has just been recorded and inserted into the
  769. * database, or 'delete' if it will be deleted right after this hook
  770. * has been called.
  771. *
  772. * @param $operation
  773. * An operation array containing basic information about the commit, branch
  774. * or tag operation. It consists of the following elements:
  775. *
  776. * - 'vc_op_id': The Drupal-specific operation identifier (a simple integer)
  777. * which is unique among all operations (commits, branch ops, tag ops)
  778. * in all repositories.
  779. * - 'type': The type of the operation - one of the
  780. * VERSIONCONTROL_OPERATION_{COMMIT,BRANCH,TAG} constants.
  781. * Note that if you pass branch or tag constraints, this function might
  782. * nevertheless return commit operations too - that happens for version
  783. * control systems without native branches or tags (like Subversion)
  784. * when a branch or tag is affected by the commit.
  785. * - 'repository': The repository where this operation occurred.
  786. * This is a structured "repository array", like is returned
  787. * by versioncontrol_get_repository().
  788. * - 'date': The time when the operation was performed, given as
  789. * Unix timestamp. (For commits, this is the time when the revision
  790. * was committed, whereas for branch/tag operations it is the time
  791. * when the files were branched or tagged.)
  792. * - 'uid': The Drupal user id of the operation author, or 0 if no
  793. * Drupal user could be associated to the author.
  794. * - 'username': The system specific VCS username of the author.
  795. * - 'message': The log message for the commit, tag or branch operation.
  796. * If a version control system doesn't support messages for any of them,
  797. * this element contains an empty string.
  798. * - 'revision': The VCS specific repository-wide revision identifier,
  799. * like '' in CVS, '27491' in Subversion or some SHA-1 key in various
  800. * distributed version control systems. If there is no such revision
  801. * (which may be the case for version control systems that don't support
  802. * atomic commits) then the 'revision' element is an empty string.
  803. * For branch and tag operations, this element indicates the
  804. * (repository-wide) revision of the files that were branched or tagged.
  805. *
  806. * - 'labels': An array of branches or tags that were affected by this
  807. * operation. Branch and tag operations are known to only affect one
  808. * branch or tag, so for these there will be only one element (with 0
  809. * as key) in 'labels'. Commits might affect any number of branches,
  810. * including none. Commits that emulate branches and/or tags (like
  811. * in Subversion, where they're not a native concept) can also include
  812. * add/delete/move operations for labels, as detailed below.
  813. * Mind that the main development branch - e.g. 'HEAD', 'trunk'
  814. * or 'master' - is also considered a branch. Each element in 'labels'
  815. * is a structured array with the following keys:
  816. *
  817. * - 'id': The label identifier (a simple integer), used for unique
  818. * identification of branches and tags in the database.
  819. * - 'name': The branch or tag name (a string).
  820. * - 'action': Specifies what happened to this label in this operation.
  821. * For plain commits, this is always VERSIONCONTROL_ACTION_MODIFIED.
  822. * For branch or tag operations (or commits that emulate those),
  823. * it can be either VERSIONCONTROL_ACTION_ADDED or
  824. * VERSIONCONTROL_ACTION_DELETED.
  825. *
  826. * @param $operation_items
  827. * A structured array containing all items that were affected by the above
  828. * operation. Array keys are the current/new paths, even if the item doesn't
  829. * exist anymore (as is the case with delete actions in commits).
  830. * The associated array elements are structured item arrays and consist of
  831. * the following elements:
  832. *
  833. * - 'type': Specifies the item type, which is either
  834. * VERSIONCONTROL_ITEM_FILE or VERSIONCONTROL_ITEM_DIRECTORY for items
  835. * that still exist, or VERSIONCONTROL_ITEM_FILE_DELETED respectively
  836. * VERSIONCONTROL_ITEM_DIRECTORY_DELETED for items that have been
  837. * removed (by a commit's delete action).
  838. * - 'path': The path of the item at the specific revision.
  839. * - 'revision': The (file-level) revision when the item was changed.
  840. * If there is no such revision (which may be the case for
  841. * directory items) then the 'revision' element is an empty string.
  842. * - 'item_revision_id': Identifier of this item revision in the database.
  843. * Note that you can only rely on this element to exist for
  844. * operation items - functions that interface directly with the VCS
  845. * (such as versioncontrol_get_directory_contents() or
  846. * versioncontrol_get_parallel_items()) might not include
  847. * this identifier, for obvious reasons.
  848. *
  849. * For commit operations, additional information about the origin of
  850. * the items is also available. The following elements will be set
  851. * for each item in addition to the ones listed above:
  852. *
  853. * - 'action': Specifies how the item was changed.
  854. * One of the predefined VERSIONCONTROL_ACTION_* values.
  855. * - 'source_items': An array with the previous state(s) of the affected item.
  856. * Empty if 'action' is VERSIONCONTROL_ACTION_ADDED.
  857. * - 'replaced_item': The previous but technically unrelated item at the
  858. * same location as the current item. Only exists if this previous item
  859. * was deleted and replaced by a different one that was just moved
  860. * or copied to this location.
  861. */
  862. function versioncontrol_fakevcs_operation($op, $operation, $operation_items) {
  863. // Mmkay, with Version Control API not being able to extend operations
  864. // anymore like in 5.x-1.x, I'm running out of good examples for this hook.
  865. // But let's say we want to store the original branch for a commit, so that
  866. // we can improve commit visualizations (should Version Control API
  867. // respectively Commit Log support that sometime in the future).
  868. if ($operation['type'] != VERSIONCONTROL_OPERATION_COMMIT) {
  869. return; // Not interested in branch and tag operations.
  870. }
  871. switch ($op) {
  872. case 'insert':
  873. foreach ($operation['labels'] as $label) {
  874. db_query(
  875. "INSERT INTO {versioncontrol_fakevcs_original_commit_branches}
  876. (vc_op_id, label_id) VALUES (%d, %d)",
  877. $operation['vc_op_id'], $label['label_id']
  878. );
  879. }
  880. break;
  881. case 'delete':
  882. db_query('DELETE FROM {versioncontrol_fakevcs_original_commit_branches}
  883. WHERE vc_op_id = %d', $operation['vc_op_id']);
  884. break;
  885. }
  886. }
  887. /**
  888. * Implementation of [versioncontrol_backend]_account():
  889. * Manage (insert, update or delete) additional FakeVCS user account data
  890. * in the database.
  891. *
  892. * This function is optional for backend modules to implement. If you don't
  893. * need custom repository data (or you let the Version Control API manage it),
  894. * just don't implement it.
  895. *
  896. * @param $op
  897. * Either 'insert' when the account is in the process of being created,
  898. * or 'update' when username or VCS specific data change,
  899. * or 'delete' if it will be deleted after this function has been called.
  900. * @param $uid
  901. * The Drupal user id corresponding to the VCS account.
  902. * @param $username
  903. * The VCS specific username (a string).
  904. * @param $repository
  905. * The repository where the user has its VCS account.
  906. * @param $additional_data
  907. * An array of additional author information.
  908. */
  909. function versioncontrol_fakevcs_account($op, $uid, $username, $repository, $additional_data = array()) {
  910. $fakevcs_specific = $additional_data['fakevcs_specific'];
  911. switch ($op) {
  912. case 'insert':
  913. if (!isset($fakevcs_specific) || !isset($fakevcs_specific['password'])) {
  914. drupal_set_message(t('Error: no FakeVCS password given on account creation!'), 'error');
  915. return;
  916. }
  917. db_query("INSERT INTO {versioncontrol_fakevcs_accounts}
  918. (uid, repo_id, password)
  919. VALUES (%d, %d, '%s')",
  920. $uid, $repository['repo_id'], $fakevcs_specific['password']);
  921. break;
  922. case 'update':
  923. if (!isset($fakevcs_specific) || !isset($fakevcs_specific['password'])) {
  924. return; // the user didn't update the password in the process.
  925. }
  926. db_query("UPDATE {versioncontrol_fakevcs_accounts}
  927. SET password = '%s'
  928. WHERE uid = %d AND repo_id = %d",
  929. $fakevcs_specific['password'], $uid, $repository['repo_id']);
  930. if (!user_access('administer version control systems')) {
  931. // Admins get "The account has been updated successfully" anyways.
  932. drupal_set_message(t('The FakeVCS password has been updated successfully.'));
  933. }
  934. break;
  935. case 'delete':
  936. db_query('DELETE FROM {versioncontrol_fakevcs_accounts}
  937. WHERE uid = %d AND repo_id = %d',
  938. $uid, $repository['repo_id']);
  939. break;
  940. }
  941. }
  942. /**
  943. * Implementation of [versioncontrol_backend]_repository():
  944. * Manage (insert, update or delete) additional FakeVCS repository data
  945. * in the database.
  946. *
  947. * This function is optional for backend modules to implement. If you don't
  948. * need custom repository data (or you let the Version Control API manage it),
  949. * just don't implement it.
  950. *
  951. * @param $op
  952. * Either 'insert' when the repository has just been created, or 'update'
  953. * when repository name, root, URL backend or module specific data change,
  954. * or 'delete' if it will be deleted after this function has been called.
  955. *
  956. * @param $repository
  957. * The repository array containing the repository. It's a single
  958. * repository array like the one returned by versioncontrol_get_repository(),
  959. * so it consists of the following elements:
  960. *
  961. * - 'repo_id': The unique repository id.
  962. * - 'name': The user-visible name of the repository.
  963. * - 'vcs': The unique string identifier of the version control system
  964. * that powers this repository.
  965. * - 'root': The root directory of the repository. In most cases,
  966. * this will be a local directory (e.g. '/var/repos/drupal'),
  967. * but it may also be some specialized string for remote repository
  968. * access. How this string may look like depends on the backend.
  969. * - 'authorization_method': The string identifier of the repository's
  970. * authorization method, that is, how users may register accounts
  971. * in this repository. Modules can provide their own methods
  972. * by implementing hook_versioncontrol_authorization_methods().
  973. * - 'url_backend': The prefix (excluding the trailing underscore)
  974. * for URL backend retrieval functions.
  975. * - '[xxx]_specific': An array of VCS specific additional repository
  976. * information. How this array looks like is defined by the
  977. * corresponding backend module (versioncontrol_[xxx]).
  978. */
  979. function versioncontrol_fakevcs_repository($op, $repository) {
  980. if ($op == 'delete') {
  981. db_query('DELETE FROM {versioncontrol_fakevcs_repository_ponies}
  982. WHERE repo_id = %d', $repository['repo_id']);
  983. }
  984. }
  985. /**
  986. * Implementation of [vcs_backend]_import_accounts():
  987. * Import accounts into a repository, given text data from the accounts file.
  988. * No accounts are deleted, new accounts are inserted, and existing accounts
  989. * are updated with imported ones.
  990. *
  991. * This function is optional for backend modules to implement. If it's not
  992. * implemented, the user will simply not be offered import functionality.
  993. *
  994. * @param $repository
  995. * The repository where the accounts will be imported.
  996. * @param $data
  997. * The contents of the "account data" text area where the user has to
  998. * enter/copy the contents of the version control system's accounts file.
  999. */
  1000. function versioncontrol_fakevcs_import_accounts($repository, $data) {
  1001. $accounts = versioncontrol_fakevcs_parse_account_data($repository, $data);
  1002. foreach ($accounts as $account) {
  1003. $additional_data = array(
  1004. 'fakevcs_specific' => array('password' => $password),
  1005. );
  1006. $username = $account['username'];
  1007. $uid = versioncontrol_get_account_uid_for_username($repository['repo_id'], $username, TRUE);
  1008. if (isset($uid)) {
  1009. versioncontrol_update_account($repository, $uid, $username, $additional_data);
  1010. $names[] = t('updated !username', array('!username' => $username));
  1011. }
  1012. else {
  1013. $uid = db_result(db_query("SELECT uid FROM {users} WHERE name = '%s'", $username));
  1014. if ($uid) {
  1015. versioncontrol_insert_account($repository, $uid, $username, $additional_data);
  1016. $names[] = t('added !username', array('!username' => $username));
  1017. }
  1018. else {
  1019. $names[] = t('didn\'t add !username (no matching Drupal username exists)',
  1020. array('!username' => $username));
  1021. }
  1022. }
  1023. }
  1024. }
  1025. /**
  1026. * Implementation of [vcs_backend]_export_accounts():
  1027. * Export accounts of a repository to text data that is suitable for
  1028. * copying to the version control system's accounts file.
  1029. *
  1030. * This function is optional for backend modules to implement. If it's not
  1031. * implemented, the user will simply not be offered export functionality.
  1032. *
  1033. * @param $repository
  1034. * The repository whose accounts will be exported.
  1035. * @param $accounts
  1036. * The list (array) of accounts that should be exported, given in the same
  1037. * format as the return value of versioncontrol_get_accounts().
  1038. * All accounts in this list are from the above repository.
  1039. *
  1040. * @return
  1041. * The exported textual representation of the account list.
  1042. */
  1043. function versioncontrol_fakevcs_export_accounts($repository, $accounts) {
  1044. if (empty($accounts)) {
  1045. return '# '. t('no user accounts available to export');
  1046. }
  1047. $accounts_flat = array();
  1048. $uid_constraints = array();
  1049. $params = array($repository['repo_id']);
  1050. foreach ($accounts as $uid => $usernames_per_repository) {
  1051. foreach ($usernames_per_repository as $repo_id => $username) {
  1052. $accounts_flat[$uid] = array('uid' => $uid, 'username' => $username);
  1053. $uid_constraints[] = 'uid = %d';
  1054. $params[] = $uid;
  1055. }
  1056. }
  1057. $result = db_query('SELECT uid, password FROM {versioncontrol_fakevcs_accounts}
  1058. WHERE repo_id = %d
  1059. AND ('. implode(' OR ', $uid_constraints) .')',
  1060. $params);
  1061. while ($account = db_fetch_object($result)) {
  1062. $accounts_flat[$account->uid]['password'] = $account->password;
  1063. }
  1064. $data = '';
  1065. foreach ($accounts_flat as $uid => $account) {
  1066. $data .= '# '. url('user/'. $uid, NULL, NULL, TRUE) ."\n";
  1067. $data .= $account['username'] .':'. $account['password'] ."\n";
  1068. }
  1069. return $data;
  1070. }