Class: Repository::Cvs

Inherits:
Repository
  • Object
show all
Defined in:
app/models/repository/cvs.rb

Constant Summary

Constants inherited from Repository

IDENTIFIER_MAX_LENGTH

Class Method Summary collapse

Instance Method Summary collapse

Methods inherited from Repository

#<=>, available_scm, #branches, #committer_ids=, #committers, #default_branch, #diff_format_revisions, #entries, #extra_info, factory, fetch_changesets, find_by_identifier_param, #find_changeset_by_name, #find_committer_user, #identifier=, #identifier_frozen?, #identifier_param, #latest_changeset, #latest_changesets, #merge_extra_info, #name, #password, #password=, #properties, #relative_path, #repo_create_validation, #repo_log_encoding, #report_last_commit, repository_class, #root_url=, #same_commits_in_scope, scan_changesets_for_issue_ids, #scan_changesets_for_issue_ids, #scm, #scm_adapter, scm_available, scm_command, #scm_name, scm_version_string, #set_as_default?, #stats_by_author, #supports_all_revisions?, #supports_annotate?, #supports_cat?, #supports_directory_revisions?, #supports_revision_graph?, #tags, #url=

Methods included from Redmine::SafeAttributes

#delete_unsafe_attributes, included, #safe_attribute?, #safe_attribute_names, #safe_attributes=

Methods included from Redmine::Ciphering

cipher_key, decrypt_text, encrypt_text, included, logger

Class Method Details

.human_attribute_name(attribute_key_name, *args) ⇒ Object



27
28
29
30
31
32
33
34
35
# File 'app/models/repository/cvs.rb', line 27

def self.human_attribute_name(attribute_key_name, *args)
  attr_name = attribute_key_name.to_s
  if attr_name == "root_url"
    attr_name = "cvsroot"
  elsif attr_name == "url"
    attr_name = "cvs_module"
  end
  super(attr_name, *args)
end

.scm_adapter_classObject



37
38
39
# File 'app/models/repository/cvs.rb', line 37

def self.scm_adapter_class
  Redmine::Scm::Adapters::CvsAdapter
end

.scm_nameObject



41
42
43
# File 'app/models/repository/cvs.rb', line 41

def self.scm_name
  'CVS'
end

Instance Method Details

#annotate(path, identifier = nil) ⇒ Object



85
86
87
88
89
90
91
92
# File 'app/models/repository/cvs.rb', line 85

def annotate(path, identifier=nil)
  rev = nil
  if ! identifier.nil?
    rev = changesets.find_by_revision(identifier)
    return nil if rev.nil?
  end
  scm.annotate(path, rev.nil? ? nil : rev.committed_on)
end

#cat(path, identifier = nil) ⇒ Object



76
77
78
79
80
81
82
83
# File 'app/models/repository/cvs.rb', line 76

def cat(path, identifier=nil)
  rev = nil
  if ! identifier.nil?
    rev = changesets.find_by_revision(identifier)
    return nil if rev.nil?
  end
  scm.cat(path, rev.nil? ? nil : rev.committed_on)
end

#diff(path, rev, rev_to) ⇒ Object



94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
# File 'app/models/repository/cvs.rb', line 94

def diff(path, rev, rev_to)
  # convert rev to revision. CVS can't handle changesets here
  diff=[]
  changeset_from = changesets.find_by_revision(rev)
  if rev_to.to_i > 0
    changeset_to = changesets.find_by_revision(rev_to)
  end
  changeset_from.filechanges.each() do |change_from|
    revision_from = nil
    revision_to   = nil
    if path.nil? || (change_from.path.starts_with? scm.with_leading_slash(path))
      revision_from = change_from.revision
    end
    if revision_from
      if changeset_to
        changeset_to.filechanges.each() do |change_to|
          revision_to = change_to.revision if change_to.path == change_from.path
        end
      end
      unless revision_to
        revision_to = scm.get_previous_revision(revision_from)
      end
      file_diff = scm.diff(change_from.path, revision_from, revision_to)
      diff = diff + file_diff unless file_diff.nil?
    end
  end
  return diff
end

#entry(path = nil, identifier = nil) ⇒ Object



45
46
47
48
# File 'app/models/repository/cvs.rb', line 45

def entry(path=nil, identifier=nil)
  rev = identifier.nil? ? nil : changesets.find_by_revision(identifier)
  scm.entry(path, rev.nil? ? nil : rev.committed_on)
end

#fetch_changesetsObject



123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
# File 'app/models/repository/cvs.rb', line 123

def fetch_changesets
  # some nifty bits to introduce a commit-id with cvs
  # natively cvs doesn't provide any kind of changesets,
  # there is only a revision per file.
  # we now take a guess using the author, the commitlog and the commit-date.

  # last one is the next step to take. the commit-date is not equal for all
  # commits in one changeset. cvs update the commit-date when the *,v file was touched. so
  # we use a small delta here, to merge all changes belonging to _one_ changeset
  time_delta  = 10.seconds
  fetch_since = latest_changeset ? latest_changeset.committed_on : nil
  transaction do
    tmp_rev_num = 1
    scm.revisions('', fetch_since, nil, :log_encoding => repo_log_encoding) do |revision|
      # only add the change to the database, if it doen't exists. the cvs log
      # is not exclusive at all.
      tmp_time = revision.time.clone
      unless filechanges.find_by_path_and_revision(
                              scm.with_leading_slash(revision.paths[0][:path]),
                              revision.paths[0][:revision]
                           )
        cmt = Changeset.normalize_comments(revision.message, repo_log_encoding)
        author_utf8 = Changeset.to_utf8(revision.author, repo_log_encoding)
        cs  = changesets.where(
                :committed_on => tmp_time - time_delta .. tmp_time + time_delta,
                :committer    => author_utf8,
                :comments     => cmt
              ).first
        # create a new changeset....
        unless cs
          # we use a temporary revision number here (just for inserting)
          # later on, we calculate a continous positive number
          tmp_time2 = tmp_time.clone.gmtime
          branch    = revision.paths[0][:branch]
          scmid     = branch + "-" + tmp_time2.strftime("%Y%m%d-%H%M%S")
          cs = Changeset.create(:repository   => self,
                                :revision     => "tmp#{tmp_rev_num}",
                                :scmid        => scmid,
                                :committer    => revision.author,
                                :committed_on => tmp_time,
                                :comments     => revision.message)
          tmp_rev_num += 1
        end
        # convert CVS-File-States to internal Action-abbrevations
        # default action is (M)odified
        action = "M"
        if revision.paths[0][:action] == "Exp" && revision.paths[0][:revision] == "1.1"
          action = "A" # add-action always at first revision (= 1.1)
        elsif revision.paths[0][:action] == "dead"
          action = "D" # dead-state is similar to Delete
        end
        Change.create(
           :changeset => cs,
           :action    => action,
           :path      => scm.with_leading_slash(revision.paths[0][:path]),
           :revision  => revision.paths[0][:revision],
           :branch    => revision.paths[0][:branch]
            )
      end
    end

    # Renumber new changesets in chronological order
    Changeset.
      order('committed_on ASC, id ASC').
      where("repository_id = ? AND revision LIKE 'tmp%'", id).
      each do |changeset|
        changeset.update_attribute :revision, next_revision_number
      end
  end # transaction
  @current_revision_number = nil
end