Welcome to mirror list, hosted at ThFree Co, Russian Federation.

satellite.rb « satellite « gitlab « lib - gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
blob: d8e8f58963bde352e5de13a4571dcf452f90bb3d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
module Gitlab
  class SatelliteNotExistError < StandardError; end

  module Satellite
    class Satellite
      include Gitlab::Popen

      PARKING_BRANCH = "__parking_branch"

      attr_accessor :project

      def initialize(project)
        @project = project
      end

      def raise_no_satellite
        raise SatelliteNotExistError.new("Satellite doesn't exist")
      end

      def clear_and_update!
        raise_no_satellite unless exists?

        delete_heads!
        clear_working_dir!
        update_from_source!
      end

      def create
        output, status = popen("git clone #{project.url_to_repo} #{path}",
                               Gitlab.config.satellites.path)

        if status.zero?
          true
        else
          Gitlab::GitLogger.error("Failed to create satellite for #{project.name_with_namespace}")
          false
        end
      end

      def exists?
        File.exists? path
      end

      # * Locks the satellite
      # * Changes the current directory to the satellite's working dir
      # * Yields
      def lock
        raise_no_satellite unless exists?

        File.open(lock_file, "w+") do |f|
          f.flock(File::LOCK_EX)

          Dir.chdir(path) do
            return yield
          end
        end
      end

      def lock_file
        Rails.root.join("tmp", "satellite_#{project.id}.lock")
      end

      def path
        File.join(Gitlab.config.satellites.path, project.path_with_namespace)
      end

      def repo
        raise_no_satellite unless exists?

        @repo ||= Grit::Repo.new(path)
      end

      def destroy
        FileUtils.rm_rf(path)
      end

      private

      # Clear the working directory
      def clear_working_dir!
        repo.git.reset(hard: true)
      end

      # Deletes all branches except the parking branch
      #
      # This ensures we have no name clashes or issues updating branches when
      # working with the satellite.
      def delete_heads!
        heads = repo.heads.map(&:name)

        # update or create the parking branch
        if heads.include? PARKING_BRANCH
          repo.git.checkout({}, PARKING_BRANCH)
        else
          repo.git.checkout({b: true}, PARKING_BRANCH)
        end

        # remove the parking branch from the list of heads ...
        heads.delete(PARKING_BRANCH)
        # ... and delete all others
        heads.each { |head| repo.git.branch({D: true}, head) }
      end

      # Updates the satellite from Gitolite
      #
      # Note: this will only update remote branches (i.e. origin/*)
      def update_from_source!
        repo.git.fetch({timeout: true}, :origin)
      end
    end
  end
end