rfa 12 KB

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