rfa 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427
  1. #!/bin/sh
  2. # Echo help information
  3. usage()
  4. {
  5. cat <<EOF
  6. Usage: $0 [options] <command> <parameters>
  7. Tool for VCS repository administration.
  8. VCS support: $possible_vcs
  9. Options:
  10. -h, --help
  11. Print help message.
  12. -c <PATH>, --config=<PATH>
  13. Specify config file (default is /etc/repoforge/rfa.conf)
  14. -s <git/svn>, --vcs=<git/svn>
  15. Choose VCS type to create new repository (default is svn)
  16. --git
  17. Same as "-c git"
  18. --svn
  19. Same as "-c svn"
  20. Commands:
  21. add <repository1> [repository2] ...
  22. Create new repository.
  23. del <repository1> [repository2] ...
  24. Delete existing repository.
  25. fixmod <repository1> [repository2] ...
  26. Fix access rights for repository.
  27. rename <old_name> <new_name>
  28. Rename repository.
  29. useradd <repository> <r/w/rw> <user1> [user2] ...
  30. Set access rights for user(s) to repository.
  31. userdel <repository> <r/w/rw> <user1> [user2] ...
  32. Remove access rights for user(s) to repository.
  33. EOF
  34. }
  35. group_add()
  36. {
  37. groupadd -K GID_MIN=${group_gid_min} "${group_r_prefix}$1" || return 1
  38. groupadd -K GID_MIN=${group_gid_min} "${group_w_prefix}$1" || return 1
  39. }
  40. group_del()
  41. {
  42. groupdel "${group_r_prefix}$1" || return 1
  43. groupdel "${group_w_prefix}$1" || return 1
  44. }
  45. group_rename()
  46. {
  47. local old_name="$1"
  48. local new_name="$2"
  49. groupmod -n "${group_r_prefix}$new_name" "${group_r_prefix}$old_name" || return 1
  50. groupmod -n "${group_w_prefix}$new_name" "${group_w_prefix}$old_name" || return 1
  51. return 0
  52. }
  53. create_repo_svn()
  54. {
  55. svnadmin --fs-type=fsfs create "$1" || return 1
  56. }
  57. create_repo_git()
  58. {
  59. mkdir -p "$1" || return 1
  60. # git -C "$1" init --bare --shared >/dev/null || return 1
  61. cd "$1" || return 1
  62. git init --bare --shared >/dev/null || return 1
  63. cd - >/dev/null
  64. }
  65. data_add()
  66. {
  67. local r_name="$1"
  68. local r_root="$2"
  69. local r_link="$3"
  70. local repo_r="${r_root}/${r_name}"
  71. local repo_w="${r_root}/${r_name}/${r_name}"
  72. mkdir -p "${repo_r}"
  73. local saved_umask=`umask`
  74. umask 002
  75. local create_vcs_func="create_repo_$opts_vcs"
  76. $create_vcs_func "$repo_w" || return 1
  77. umask ${saved_umask}
  78. }
  79. data_fixmod()
  80. {
  81. local r_name="$1"
  82. local r_root="$2"
  83. local r_link="$3"
  84. local repo_r="${r_root}/${r_name}"
  85. local repo_w="${r_root}/${r_name}/${r_name}"
  86. chmod 750 "${repo_r}" || return 1
  87. chgrp "${group_r_prefix}${r_name}" "${repo_r}" || return 1
  88. chgrp -R "${group_w_prefix}${r_name}" "${repo_w}" || return 1
  89. local dirs=""
  90. dirs=`find "$repo_w" -type d`
  91. local dir=""
  92. for dir in $dirs; do
  93. chmod g+s "$dir" || return 1
  94. done
  95. chmod -R g+w "${repo_w}" || return 1
  96. }
  97. data_del()
  98. {
  99. local r_name="$1"
  100. local r_root="$2"
  101. rm -Rf "$r_root/$r_name"
  102. }
  103. link_add()
  104. {
  105. local r_name="$1"
  106. local r_root="$2"
  107. local r_link="$3"
  108. ln -sf "$r_root/$r_name/$r_name" "$r_link/$r_name"
  109. }
  110. link_del()
  111. {
  112. local r_name="$1"
  113. local r_link="$2"
  114. rm -f "$r_link/$r_name"
  115. }
  116. repository_add()
  117. {
  118. local rep_name=""
  119. for rep_name in "$@"; do
  120. find_repo "$rep_name"
  121. test "x$repo_root" = "x" || { echo "Error: The repository \"$rep_name\" already exists." 1>&2; exit 1; }
  122. eval repo_root="\$repository_${opts_vcs}_root"
  123. eval repo_link="\$repository_${opts_vcs}_link"
  124. test "x$repo_root" = "x" && { echo "Error: Illegal repository root \"\"" 1>&2; exit 1; }
  125. test "x$repo_link" = "x" && { echo "Error: Illegal repository link \"\"" 1>&2; exit 1; }
  126. test -d "$repo_root" || { echo "Error: Illegal repository root \"$repo_root\"" 1>&2; exit 1; }
  127. test -d "$repo_link" || { echo "Error: Illegal repository link \"$repo_link\"" 1>&2; exit 1; }
  128. group_add "$rep_name" || { echo "Error: Can't add group for repository \"$rep_name\"" 1>&2; exit 1; }
  129. data_add "$rep_name" "$repo_root" "$repo_link" || { echo "Error: Can't add repository \"$rep_name\"" 1>&2; exit 1; }
  130. data_fixmod "$rep_name" "$repo_root" "$repo_link" || { echo "Error: Can't fix mode for repository \"$rep_name\"" 1>&2; exit 1; }
  131. link_add "$rep_name" "$repo_root" "$repo_link" || { echo "Error: Can't add link for repository \"$rep_name\"" 1>&2; exit 1; }
  132. echo "The repository \"$rep_name\" was succesfully created."
  133. done
  134. }
  135. repository_del()
  136. {
  137. local rep_name=""
  138. local sure=""
  139. for rep_name in "$@"; do
  140. find_repo "$rep_name"
  141. test "x$repo_root" = "x" -o "x$repo_link" = "x" && { echo "Error: Can't find repository \"$rep_name\"" 1>&2; exit 1; }
  142. if test "x$opts_force" = "x"; then
  143. read -r -p "Deleting repository \"$rep_name\". Are you sure (y/n)? " sure
  144. test "x$sure" = "xy" -o "x$sure" = "xY" || { echo "The repository \"$rep_name\" will be not deleted."; continue; }
  145. fi
  146. link_del "$rep_name" "$repo_link" || { echo "Error: Can't remove link for repository \"$rep_name\"" 1>&2; exit 1; }
  147. data_del "$rep_name" "$repo_root" || { echo "Error: Can't remove repository \"$rep_name\"" 1>&2; exit 1; }
  148. group_del "$rep_name" || { echo "Error: Can't remove group for repository \"$rep_name\"" 1>&2; exit 1; }
  149. echo "The repository \"$rep_name\" was succesfully deleted."
  150. done
  151. }
  152. repository_fixmod()
  153. {
  154. local rep_name=""
  155. for rep_name in "$@"; do
  156. find_repo "$rep_name"
  157. test "x$repo_root" = "x" -o "x$repo_link" = "x" && { echo "Error: Can't find repository \"$rep_name\"" 1>&2; exit 1; }
  158. data_fixmod "$rep_name" "$repo_root" "$repo_link" || { echo "Error: Can't fix repository's \"$rep_name\" mode" 1>&2; exit 1; }
  159. link_add "$rep_name" "$repo_root" "$repo_link" || { echo "Error: Can't create link for repository \"$rep_name\"" 1>&2; exit 1; }
  160. echo "The repository \"$rep_name\" was succesfully fixed."
  161. done
  162. }
  163. repository_rename()
  164. {
  165. local old_name="$1"
  166. local new_name="$2"
  167. local repo_root
  168. local repo_link
  169. # Check if target name is already exists
  170. repo_root=`find_repo_root "$new_name"`
  171. test "x$repo_root" = "x" || { echo "Error: The repository \"$new_name\" is already exist" 1>&2; return 1; }
  172. repo_root=`find_repo_root "$old_name"`
  173. repo_link=`find_repo_link "$old_name"`
  174. test "x$repo_root" != "x" -a -d "$repo_root/$old_name" || { echo "Error: Can't find repository \"$old_name\"" 1>&2; return 1; }
  175. test "x$repo_root" != "x" -a -L "$repo_link/$old_name" || { echo "Error: Can't find link of repository \"$old_name\"" 1>&2; return 1; }
  176. # Real move repository and link
  177. mv -f "$repo_root/$old_name" "$repo_root/$new_name" || { echo "Error: Can't move repository \"$old_name\"" 1>&2; return 1; }
  178. link_del "$old_name" "$repo_link" || { echo "Error: Can't remove link for repository \"$old_name\"" 1>&2; }
  179. link_add "$new_name" "$repo_root" "$repo_link" || { echo "Error: Can't create link for repository \"$new_name\"" 1>&2; }
  180. # Rename a groups
  181. group_rename "$old_name" "$new_name" || { echo "Error: Can't rename access groups for repository \"$new_name\"" 1>&2; }
  182. echo "Info: The repository \"$old_name\" was succesfully renamed to \"$new_name\""
  183. return 0
  184. }
  185. user_add()
  186. {
  187. local w=0
  188. local r=0
  189. local repository_name="$1"
  190. local user_name=""
  191. shift
  192. case "$1" in
  193. r)
  194. r=1
  195. ;;
  196. w)
  197. w=1
  198. ;;
  199. rw|wr)
  200. r=1
  201. w=1
  202. ;;
  203. *)
  204. echo "Error: Illegal parameter \"$1\"" 1>&2
  205. exit 1
  206. ;;
  207. esac
  208. shift
  209. for user_name in "$@"; do
  210. test $r -ne 0 && adduser "${user_name}" "${group_r_prefix}${repository_name}"
  211. test $w -ne 0 && adduser "${user_name}" "${group_w_prefix}${repository_name}"
  212. done
  213. }
  214. user_del()
  215. {
  216. local w=0
  217. local r=0
  218. local repository_name=$1
  219. local user_name=""
  220. shift
  221. case "$1" in
  222. r)
  223. r=1
  224. ;;
  225. w)
  226. w=1
  227. ;;
  228. rw|wr)
  229. r=1
  230. w=1
  231. ;;
  232. *)
  233. echo "Error: Illegal parameter \"$1\"" 1>&2
  234. exit 1
  235. ;;
  236. esac
  237. shift
  238. for user_name in "$@"; do
  239. test $r -ne 0 && deluser "${user_name}" "${group_r_prefix}${repository_name}"
  240. test $w -ne 0 && deluser "${user_name}" "${group_w_prefix}${repository_name}"
  241. done
  242. }
  243. # Find repository root path by repository name
  244. find_repo_root()
  245. {
  246. local r=""
  247. local r_root=""
  248. for r in $possible_vcs; do
  249. eval r_root="\$repository_${r}_root"
  250. test "x$r_root" = "x" && continue
  251. test -d "$r_root/$1" || continue
  252. echo "$r_root"
  253. break
  254. done
  255. return 0
  256. }
  257. find_repo_link()
  258. {
  259. local r=""
  260. local r_root=""
  261. local r_link=""
  262. for r in $possible_vcs; do
  263. eval r_root="\$repository_${r}_root"
  264. test "x$r_root" = "x" && continue
  265. test -d "$r_root/$1" || continue
  266. eval r_link="\$repository_${r}_link"
  267. echo "$r_link"
  268. break
  269. done
  270. return 0
  271. }
  272. # Legacy function to be compatible.
  273. # Use find_repo_root and find_repo_link functions
  274. find_repo()
  275. {
  276. repo_root=`find_repo_root "$1"`
  277. repo_link=`find_repo_link "$1"`
  278. return 0
  279. }
  280. #------------------ MAIN -----------------------------------------
  281. possible_vcs="svn git"
  282. # Defaults for rfa.conf
  283. group_gid_min="3000"
  284. group_w_prefix="vcs-w-"
  285. group_r_prefix="vcs-r-"
  286. repository_root=
  287. repository_link=
  288. default_vcs="git"
  289. # Parse command line options
  290. action="help"
  291. opts_force=""
  292. opts_conf="/etc/repoforge/rfa.conf"
  293. opts_vcs="$default_vcs"
  294. while test "x$1" != "x"; do
  295. option="$1"
  296. case "$option" in
  297. -h|--help)
  298. usage
  299. exit 0
  300. ;;
  301. -f|--force)
  302. opts_force=1
  303. ;;
  304. # Config file
  305. -c)
  306. shift
  307. opts_conf="$1"
  308. ;;
  309. --config=*)
  310. opts_conf=`echo "$option" | sed 's/--config=//'`
  311. ;;
  312. # Choose VCS
  313. -s)
  314. shift
  315. opts_vcs="$1"
  316. ;;
  317. --vcs=*)
  318. opts_vcs=`echo "$option" | sed 's/--vcs=//'`
  319. ;;
  320. --git)
  321. opts_vcs="git"
  322. ;;
  323. --svn)
  324. opts_vcs="svn"
  325. ;;
  326. # Default
  327. *)
  328. action="$option"
  329. shift
  330. break
  331. ;;
  332. esac
  333. shift
  334. done
  335. # Early help message
  336. test "x$action" = "xhelp" && { usage; exit 0; }
  337. # Check options
  338. bad_vcs=1
  339. for v in $possible_vcs; do
  340. test "x$opts_vcs" = "x$v" && { bad_vcs=""; break; }
  341. done
  342. test "x$bad_vcs" = "x" || { echo "Error: Illegal VCS \"$opts_vcs\"" 1>&2; exit 1; }
  343. # Include config file
  344. test -r "$opts_conf" && . $opts_conf
  345. # Compatibility (suppose SVN)
  346. test "x$repository_svn_root" = "x" && repository_svn_root="$repository_root"
  347. test "x$repository_svn_link" = "x" && repository_svn_link="$repository_link"
  348. # Action
  349. case "$action" in
  350. "add")
  351. test $# -lt 1 && { echo "Error: Repository name is expected" 1>&2; exit 1; }
  352. repository_add "$@"
  353. ;;
  354. "del")
  355. test $# -lt 1 && { echo "Error: Repository name is expected" 1>&2; exit 1; }
  356. repository_del "$@"
  357. ;;
  358. "fixmod")
  359. test $# -lt 1 && { echo "Error: Repository name is expected" 1>&2; exit 1; }
  360. repository_fixmod "$@"
  361. ;;
  362. "rename")
  363. test $# -lt 2 && { echo "Error: The old and new repository names are expected" 1>&2; exit 1; }
  364. repository_rename "$@" || exit 1
  365. ;;
  366. "adduser"|"useradd")
  367. test $# -lt 3 && { echo "Error: Not enough parameters" 1>&2; exit 1; }
  368. user_add "$@"
  369. ;;
  370. "deluser"|"userdel")
  371. test $# -lt 3 && { echo "Error: Not enough parameters" 1>&2; exit 1; }
  372. user_del "$@"
  373. ;;
  374. *)
  375. echo "Error: Unknown command" 1>&2
  376. exit 1
  377. ;;
  378. esac
  379. exit $?