/*
 * Copyright 2015 dick the deployer.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.dickthedeployer.dick.web.service;

import com.dickthedeployer.dick.web.domain.Project;
import com.google.common.base.Throwables;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.concurrent.ConcurrentHashMap;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

/**
 *
 * @author mariusz
 */
@Service
public class RepositoryService {

    private final static ConcurrentHashMap<Project, Path> REPOS = new ConcurrentHashMap<>();

    @Autowired
    CommandService commandService;

    public InputStream getFile(Project project, String sha, String filePath) {
        checkoutRepository(project);
        Path path = REPOS.get(project);
        checkoutRevision(path, project.getRef(), sha);
        Path file = path.resolve(filePath);
        try {
            if (Files.exists(file)) {
                return Files.newInputStream(file);
            } else {
                return null;
            }
        } catch (IOException ex) {
            throw Throwables.propagate(ex);
        }
    }

    private void checkoutRepository(Project project) {
        REPOS.computeIfAbsent(project, (key)
                -> {
                    try {
                        Path path = Files.createTempDirectory(getPrefix(key, project.getRef()));
                        initializeRepository(path, project);
                        return path;
                    } catch (IOException ex) {
                        throw Throwables.propagate(ex);
                    }
                });
    }

    private String getPrefix(Project project, String ref) {
        return project.getName().replaceAll("/", "-") + ref;
    }

    private void initializeRepository(Path path, Project stack) {
        commandService.invoke(path, "git", "init");
        commandService.invoke(path, "git", "clone", stack.getRepository());
        commandService.invoke(path, "git", "remote", "add", "origin", stack.getRepository());
    }

    private void checkoutRevision(Path path, String ref, String sha) {
        commandService.invoke(path, "git", "pull", "origin", ref);
        commandService.invoke(path, "git", "checkout", sha);
    }
}

@@ -752,24 +752,138 @@
 hrowables;%0D%0A
+import org.springframework.beans.factory.annotation.Autowired;%0D%0Aimport org.springframework.stereotype.Service;%0D%0A%0D%0A
 import java.
@@ -1036,120 +1036,8 @@
 ap;%0D
-%0Aimport org.springframework.beans.factory.annotation.Autowired;%0D%0Aimport org.springframework.stereotype.Service;%0D
 %0A%0D%0A/
@@ -1416,32 +1416,67 @@
 .get(project);%0D%0A
+        synchronized (path) %7B%0D%0A    
         checkout
@@ -1519,24 +1519,28 @@
 );%0D%0A        
+   
+ 
 Path file = 
@@ -1564,32 +1564,36 @@
 Path);%0D%0A        
+    
 try %7B%0D%0A         
@@ -1595,16 +1595,20 @@
         
+ 
+   
 if (File
@@ -1638,24 +1638,28 @@
             
+   
+ 
 return Files
@@ -1694,16 +1694,20 @@
         
+    
 %7D else %7B
@@ -1720,24 +1720,28 @@
             
+  
+  
 return null;
@@ -1742,16 +1742,20 @@
  null;%0D%0A
+    
         
@@ -1761,32 +1761,36 @@
      %7D%0D%0A        
+    
 %7D catch (IOExcep
@@ -1793,32 +1793,36 @@
 xception ex) %7B%0D%0A
+    
             thro
@@ -1842,32 +1842,36 @@
 propagate(ex);%0D%0A
+    
         %7D%0D%0A    %7D
@@ -1861,24 +1861,35 @@
          %7D%0D%0A
+        %7D%0D%0A
     %7D%0D%0A%0D%0A   
@@ -1889,32 +1889,45 @@
 %0D%0A%0D%0A    private 
+synchronized 
 void checkoutRep

Synchronize on repository operations