PageRenderTime 47ms CodeModel.GetById 23ms RepoModel.GetById 1ms app.codeStats 0ms

/lib/bitbucket-backup/repository.rb

https://bitbucket.org/mariusmarais/bitbucket-backup
Ruby | 158 lines | 106 code | 30 blank | 22 comment | 7 complexity | c9af5c845e64f21a7da59b7713de115b MD5 | raw file
Possible License(s): 0BSD
  1. require "fileutils"
  2. require "cgi"
  3. require "open3"
  4. module Bitbucket
  5. module Backup
  6. class Repository
  7. # @return [Hash]
  8. # the hash of repo data from the Bitbucket API.
  9. #
  10. attr_reader :repo
  11. # @return [String]
  12. # the plain-text password for the repo.
  13. #
  14. attr_reader :password
  15. # @return [String]
  16. # the absolute path of the directory to backup the repo to.
  17. #
  18. attr_reader :backup_root
  19. # Creates a new repo.
  20. #
  21. # @param [Hash] repo
  22. # the hash of repo data from the Bitbucket API.
  23. #
  24. # @param [String] password
  25. # the plain-text passsword for the repo.
  26. #
  27. # @param [String] backup_root
  28. # the absolute path of the directory to backup the repo to.
  29. #
  30. def initialize(repo, password, backup_root)
  31. @repo = repo
  32. @password = password
  33. @backup_root = backup_root
  34. end
  35. # Performs a backup of the repository.
  36. #
  37. def backup
  38. puts "Backing up: #{repo["slug"]}."
  39. unless Bitbucket::Backup.have_scm_tool?(repo["scm"])
  40. puts "Warning: #{repo["scm"]} not found on PATH. Skipping..."
  41. return
  42. end
  43. backup_src
  44. backup_wiki
  45. end
  46. private
  47. def backup_src
  48. clone_or_update(:type => :src)
  49. end
  50. def backup_wiki
  51. clone_or_update(:type => :wiki) if repo["has_wiki"]
  52. end
  53. def clone_or_update(options)
  54. path = dir_for_repo(options)
  55. uri = uri_for_repo(options)
  56. if File.exist?(path)
  57. run_incremental_backup(path, uri)
  58. else
  59. run_full_backup(uri, path)
  60. end
  61. end
  62. def is_repo?(path)
  63. FileUtils.cd(path)
  64. case repo["scm"]
  65. when "hg"
  66. Open3.popen3("hg status")
  67. when "git"
  68. Open3.popen3("git status")
  69. end
  70. return $.
  71. end
  72. def run_incremental_backup(path, uri)
  73. unless is_repo?(path)
  74. puts "Warning: file already exists but is not a repo!! Skipping..."
  75. return false
  76. end
  77. FileUtils.cd(path)
  78. case repo["scm"]
  79. when "hg"
  80. system "hg pull -u #{uri}"
  81. when "git"
  82. system "git pull #{uri}"
  83. end
  84. end
  85. def run_full_backup(uri, dest)
  86. case repo["scm"]
  87. when "hg"
  88. system "hg clone #{uri} #{dest}"
  89. when "git"
  90. system "git clone #{uri} #{dest}"
  91. end
  92. end
  93. def dir_for_repo(options)
  94. if options.nil? || options[:type].nil?
  95. raise RuntimeError
  96. end
  97. path = nil
  98. case options[:type]
  99. when :src
  100. path = File.expand_path("#{backup_root}/#{repo["slug"]}/src")
  101. when :wiki
  102. path = File.expand_path("#{backup_root}/#{repo["slug"]}/wiki")
  103. end
  104. return path
  105. end
  106. def uri_for_repo(options)
  107. base_uri = nil
  108. uri = nil
  109. ext = nil
  110. if repo["scm"] == "git"
  111. ext = ".git"
  112. end
  113. if repo["is_private"]
  114. base_uri = "https://#{repo["owner"]}:#{CGI.escape(password)}@bitbucket.org/#{repo["owner"]}/#{repo["slug"]}#{ext}"
  115. else
  116. base_uri = "https://bitbucket.org/#{repo["owner"]}/#{repo["slug"]}#{ext}"
  117. end
  118. case options[:type]
  119. when :src
  120. uri = base_uri
  121. when :wiki
  122. uri = "#{base_uri}/wiki"
  123. end
  124. return uri
  125. end
  126. end
  127. end
  128. end