4b9aec924eafdf1c7175f8147ed356b0b5ab4fe8
[idea/community.git] / plugins / svn4idea / src / org / jetbrains / idea / svn / history / SvnRepositoryContentRevision.java
1 /*
2  * Copyright 2000-2009 JetBrains s.r.o.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 /*
18  * Created by IntelliJ IDEA.
19  * User: yole
20  * Date: 28.11.2006
21  * Time: 17:48:18
22  */
23 package org.jetbrains.idea.svn.history;
24
25 import com.intellij.openapi.application.ApplicationManager;
26 import com.intellij.openapi.progress.ProgressIndicator;
27 import com.intellij.openapi.progress.ProgressManager;
28 import com.intellij.openapi.util.io.FileUtil;
29 import com.intellij.openapi.vcs.FilePath;
30 import com.intellij.openapi.vcs.VcsException;
31 import com.intellij.openapi.vcs.changes.ByteBackedContentRevision;
32 import com.intellij.openapi.vcs.impl.ContentRevisionCache;
33 import com.intellij.openapi.vfs.LocalFileSystem;
34 import com.intellij.vcsUtil.VcsUtil;
35 import org.jetbrains.annotations.NotNull;
36 import org.jetbrains.annotations.Nullable;
37 import org.jetbrains.idea.svn.*;
38 import org.jetbrains.idea.svn.commandLine.SvnBindException;
39 import org.tmatesoft.svn.core.wc.SVNRevision;
40 import org.tmatesoft.svn.core.wc2.SvnTarget;
41
42 import java.io.ByteArrayOutputStream;
43 import java.io.IOException;
44 import java.io.OutputStream;
45
46 import static com.intellij.util.ObjectUtils.notNull;
47
48 public class SvnRepositoryContentRevision extends SvnBaseContentRevision implements ByteBackedContentRevision {
49
50   @NotNull private final String myPath;
51   private final long myRevision;
52
53   public SvnRepositoryContentRevision(@NotNull SvnVcs vcs, @NotNull FilePath remotePath, @Nullable FilePath localPath, long revision) {
54     super(vcs, notNull(localPath, remotePath));
55     myPath = FileUtil.toSystemIndependentName(remotePath.getPath());
56     myRevision = revision;
57   }
58
59   @NotNull
60   public String getContent() throws VcsException {
61     return ContentRevisionCache.getAsString(getContentAsBytes(), myFile, null);
62   }
63
64   @NotNull
65   @Override
66   public byte[] getContentAsBytes() throws VcsException {
67     try {
68       if (myFile.getVirtualFile() == null) {
69         LocalFileSystem.getInstance().refreshAndFindFileByPath(myFile.getPath());
70       }
71       return ContentRevisionCache.getOrLoadAsBytes(myVcs.getProject(), myFile, getRevisionNumber(), myVcs.getKeyInstanceMethod(),
72                                                    ContentRevisionCache.UniqueType.REPOSITORY_CONTENT, () -> loadContent().toByteArray());
73     }
74     catch (IOException e) {
75       throw new VcsException(e);
76     }
77   }
78
79   @NotNull
80   protected ByteArrayOutputStream loadContent() throws VcsException {
81     final ByteArrayOutputStream buffer = new ByteArrayOutputStream();
82     ContentLoader loader = new ContentLoader(myPath, buffer, myRevision);
83     if (ApplicationManager.getApplication().isDispatchThread()) {
84       ProgressManager.getInstance()
85         .runProcessWithProgressSynchronously(loader, SvnBundle.message("progress.title.loading.file.content"), false, null);
86     }
87     else {
88       loader.run();
89     }
90     final Exception exception = loader.getException();
91     if (exception != null) {
92       throw new VcsException(exception);
93     }
94     ContentRevisionCache.checkContentsSize(myPath, buffer.size());
95     return buffer;
96   }
97
98   @NotNull
99   public SvnRevisionNumber getRevisionNumber() {
100     return new SvnRevisionNumber(SVNRevision.create(myRevision));
101   }
102
103   public static SvnRepositoryContentRevision create(@NotNull SvnVcs vcs,
104                                                     @NotNull String repositoryRoot,
105                                                     @NotNull String path,
106                                                     @Nullable FilePath localPath,
107                                                     long revision) {
108     return create(vcs, SvnUtil.appendMultiParts(repositoryRoot, path), localPath, revision);
109   }
110
111   public static SvnRepositoryContentRevision createForRemotePath(@NotNull SvnVcs vcs,
112                                                                  @NotNull String repositoryRoot,
113                                                                  @NotNull String path,
114                                                                  boolean isDirectory,
115                                                                  long revision) {
116     FilePath remotePath = VcsUtil.getFilePathOnNonLocal(SvnUtil.appendMultiParts(repositoryRoot, path), isDirectory);
117     return create(vcs, remotePath, remotePath, revision);
118   }
119
120   public static SvnRepositoryContentRevision create(@NotNull SvnVcs vcs,
121                                                     @NotNull String fullPath,
122                                                     @Nullable FilePath localPath,
123                                                     long revision) {
124     // TODO: Check if isDirectory = false always true for this method calls
125     FilePath remotePath = VcsUtil.getFilePathOnNonLocal(fullPath, false);
126
127     return create(vcs, remotePath, localPath == null ? remotePath : localPath, revision);
128   }
129
130   public static SvnRepositoryContentRevision create(@NotNull SvnVcs vcs,
131                                                     @NotNull FilePath remotePath,
132                                                     @Nullable FilePath localPath,
133                                                     long revision) {
134     return remotePath.getFileType().isBinary()
135            ? new SvnRepositoryBinaryContentRevision(vcs, remotePath, localPath, revision)
136            : new SvnRepositoryContentRevision(vcs, remotePath, localPath, revision);
137   }
138
139   @Override
140   public String toString() {
141     return myFile.getIOFile() + "#" + myRevision;
142   }
143
144   private class ContentLoader implements Runnable {
145     private final String myPath;
146     private final long myRevision;
147     private final OutputStream myDst;
148     private Exception myException;
149
150     public ContentLoader(String path, OutputStream dst, long revision) {
151       myPath = path;
152       myDst = dst;
153       myRevision = revision;
154     }
155
156     public Exception getException() {
157       return myException;
158     }
159
160     public void run() {
161       ProgressIndicator progress = ProgressManager.getInstance().getProgressIndicator();
162       if (progress != null) {
163         progress.setText(SvnBundle.message("progress.text.loading.contents", myPath));
164         progress.setText2(SvnBundle.message("progress.text2.revision.information", myRevision));
165       }
166
167       try {
168         // TODO: Local path could also be used here
169         SVNRevision revision = SVNRevision.create(myRevision);
170         byte[] contents = SvnUtil.getFileContents(myVcs, SvnTarget.fromURL(SvnUtil.parseUrl(getFullPath())), revision, revision);
171         myDst.write(contents);
172       }
173       catch (VcsException e) {
174         myException = e;
175       }
176       catch (IOException e) {
177         myException = e;
178       }
179     }
180   }
181
182   @NotNull
183   public String getFullPath() {
184     return myPath;
185   }
186
187   public String getRelativePath(@NotNull String repositoryUrl) {
188     return SvnUtil.getRelativePath(repositoryUrl, myPath);
189   }
190
191   @NotNull
192   public SvnTarget toTarget() throws SvnBindException {
193     return SvnTarget.fromURL(SvnUtil.createUrl(getFullPath()), getRevisionNumber().getRevision());
194   }
195 }