diff --git a/lib/teachers_pet/actions/clone_repos.rb b/lib/teachers_pet/actions/clone_repos.rb index 6d626cb..26989d3 100755 --- a/lib/teachers_pet/actions/clone_repos.rb +++ b/lib/teachers_pet/actions/clone_repos.rb @@ -6,55 +6,99 @@ def read_info @organization = self.options[:organization] end - def load_files - @students = self.read_students_file + def students + @students ||= self.read_students_file.keys end - def get_clone_method + def web_endpoint + self.options[:web] + end + + def ssh_endpoint + @ssh_endpoint ||= self.web_endpoint.gsub("https://","git@").gsub("/",":") + end + + def clone_method self.options[:clone_method] end - def create - cloneMethod = self.get_clone_method + def clone_endpoint + if self.clone_method == 'https' + self.web_endpoint + else + self.ssh_endpoint + end + end - # create a repo for each student - self.init_client + def clone_command(username) + path = self.repo_path(username) + "git clone #{self.clone_endpoint}#{path}.git #{@repository}/#{username}" + end + + def clone(username) + command = self.clone_command(username) + puts " --> Cloning: '#{command}'" + self.execute(command) + end + + def repo_owner(username) + if self.options[:forks] + username + else + @organization + end + end + + def repo_name(username) + if self.options[:forks] + @repository + else + "#{username}-#{@repository}" + end + end + + def repo_path(username) + name = self.repo_name(username) + owner = self.repo_owner(username) + "#{owner}/#{name}" + end + + def clone_student(username) + if self.client.repository?(self.repo_owner(username), self.repo_name(username)) + self.clone(username) + else + path = self.repo_path(username) + puts " ** ERROR ** - Can't find expected repository '#{path}'" + end + end + def verify_org_exists org_hash = self.client.organization(@organization) - abort('Organization could not be found') if org_hash.nil? + if org_hash.nil? + abort('Organization could not be found') + end puts "Found organization at: #{org_hash[:url]}" + end + + def clone_all + self.init_client + + unless self.options[:forks] + self.verify_org_exists + end + + self.execute("mkdir -p #{@repository}") - # Load the teams - there should be one team per student. - org_teams = self.client.get_teams_by_name(@organization) # For each student - pull the repository if it exists puts "\nCloning assignment repositories for students..." - @students.keys.each do |student| - unless org_teams.key?(student) - puts(" ** ERROR ** - no team for #{student}") - next - end - repo_name = "#{student}-#{@repository}" - - unless self.client.repository?(@organization, repo_name) - puts " ** ERROR ** - Can't find expected repository '#{repo_name}'" - next - end - - web = self.options[:web] - sshEndpoint = web.gsub("https://","git@").gsub("/",":") - command = "git clone #{sshEndpoint}#{@organization}/#{repo_name}.git" - if cloneMethod.eql?('https') - command = "git clone #{web}#{@organization}/#{repo_name}.git" - end - puts " --> Cloning: '#{command}'" - self.execute(command) + self.students.each do |student| + self.clone_student(student) end end def run self.read_info - self.load_files - self.create + self.clone_all end end end diff --git a/lib/teachers_pet/commands/clone_repos.rb b/lib/teachers_pet/commands/clone_repos.rb index 25088be..3a979e5 100644 --- a/lib/teachers_pet/commands/clone_repos.rb +++ b/lib/teachers_pet/commands/clone_repos.rb @@ -2,6 +2,7 @@ module TeachersPet class Cli option :organization, required: true option :repository, required: true + option :forks, type: :boolean, default: false, desc: "If true, will clone forks of the repository from the provided list of students. Defaults to cloning repositories of the form /-." option :clone_method, default: 'https', desc: "'https' or 'ssh'" students_option diff --git a/spec/commands/clone_repos_spec.rb b/spec/commands/clone_repos_spec.rb index 9a7b586..c1e96f3 100644 --- a/spec/commands/clone_repos_spec.rb +++ b/spec/commands/clone_repos_spec.rb @@ -3,17 +3,19 @@ describe 'clone_repos' do include CommandHelpers - it "runs" do + it "clones all private repositories" do request_stubs = [] request_stubs << stub_get_json('https://testteacher:abc123@api.github.com/orgs/testorg', login: 'testorg', url: 'https://api.github.com/orgs/testorg' ) - request_stubs << stub_get_json('https://testteacher:abc123@api.github.com/orgs/testorg/teams?per_page=100', student_teams) + + expect_any_instance_of(TeachersPet::Actions::CloneRepos).to receive(:execute).with("mkdir -p testrepo").once + student_usernames.each do |username| request_stubs << stub_get_json("https://testteacher:abc123@api.github.com/repos/testorg/#{username}-testrepo", {}) - expect_any_instance_of(TeachersPet::Actions::CloneRepos).to receive(:execute).with("git clone https://github.com/testorg/#{username}-testrepo.git").once + expect_any_instance_of(TeachersPet::Actions::CloneRepos).to receive(:execute).with("git clone https://github.com/testorg/#{username}-testrepo.git testrepo/#{username}").once end teachers_pet(:clone_repos, @@ -30,4 +32,30 @@ expect(request_stub).to have_been_requested.once end end + + it "clones forks of a repository" do + request_stubs = [] + + expect_any_instance_of(TeachersPet::Actions::CloneRepos).to receive(:execute).with("mkdir -p testrepo").once + + student_usernames.each do |username| + request_stubs << stub_get_json("https://testteacher:abc123@api.github.com/repos/#{username}/testrepo", {}) + expect_any_instance_of(TeachersPet::Actions::CloneRepos).to receive(:execute).with("git clone https://github.com/#{username}/testrepo.git testrepo/#{username}").once + end + + teachers_pet(:clone_repos, + repository: 'testrepo', + organization: 'testorg', # TODO not actually needed + + students: students_list_fixture_path, + forks: true, + + username: 'testteacher', + password: 'abc123' + ) + + request_stubs.each do |request_stub| + expect(request_stub).to have_been_requested.once + end + end end