git-repository-provider-spec.js 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256
  1. const path = require('path');
  2. const fs = require('fs-plus');
  3. const temp = require('temp').track();
  4. const { Directory } = require('pathwatcher');
  5. const GitRepository = require('../src/git-repository');
  6. const GitRepositoryProvider = require('../src/git-repository-provider');
  7. describe('GitRepositoryProvider', () => {
  8. let provider;
  9. beforeEach(() => {
  10. provider = new GitRepositoryProvider(
  11. atom.project,
  12. atom.config,
  13. atom.confirm
  14. );
  15. });
  16. afterEach(() => {
  17. if (provider) {
  18. Object.keys(provider.pathToRepository).forEach(key => {
  19. provider.pathToRepository[key].destroy();
  20. });
  21. }
  22. });
  23. describe('.repositoryForDirectory(directory)', () => {
  24. describe('when specified a Directory with a Git repository', () => {
  25. it('resolves with a GitRepository', async () => {
  26. const directory = new Directory(
  27. path.join(__dirname, 'fixtures', 'git', 'master.git')
  28. );
  29. const result = await provider.repositoryForDirectory(directory);
  30. expect(result).toBeInstanceOf(GitRepository);
  31. expect(provider.pathToRepository[result.getPath()]).toBeTruthy();
  32. expect(result.getType()).toBe('git');
  33. // Refresh should be started
  34. await new Promise(resolve => result.onDidChangeStatuses(resolve));
  35. });
  36. it('resolves with the same GitRepository for different Directory objects in the same repo', async () => {
  37. const firstRepo = await provider.repositoryForDirectory(
  38. new Directory(path.join(__dirname, 'fixtures', 'git', 'master.git'))
  39. );
  40. const secondRepo = await provider.repositoryForDirectory(
  41. new Directory(
  42. path.join(__dirname, 'fixtures', 'git', 'master.git', 'objects')
  43. )
  44. );
  45. expect(firstRepo).toBeInstanceOf(GitRepository);
  46. expect(firstRepo).toBe(secondRepo);
  47. });
  48. });
  49. describe('when specified a Directory without a Git repository', () => {
  50. it('resolves with null', async () => {
  51. const directory = new Directory(temp.mkdirSync('dir'));
  52. const repo = await provider.repositoryForDirectory(directory);
  53. expect(repo).toBe(null);
  54. });
  55. });
  56. describe('when specified a Directory with an invalid Git repository', () => {
  57. it('resolves with null', async () => {
  58. const dirPath = temp.mkdirSync('dir');
  59. fs.writeFileSync(path.join(dirPath, '.git', 'objects'), '');
  60. fs.writeFileSync(path.join(dirPath, '.git', 'HEAD'), '');
  61. fs.writeFileSync(path.join(dirPath, '.git', 'refs'), '');
  62. const directory = new Directory(dirPath);
  63. const repo = await provider.repositoryForDirectory(directory);
  64. expect(repo).toBe(null);
  65. });
  66. });
  67. describe('when specified a Directory with a valid gitfile-linked repository', () => {
  68. it('returns a Promise that resolves to a GitRepository', async () => {
  69. const gitDirPath = path.join(
  70. __dirname,
  71. 'fixtures',
  72. 'git',
  73. 'master.git'
  74. );
  75. const workDirPath = temp.mkdirSync('git-workdir');
  76. fs.writeFileSync(
  77. path.join(workDirPath, '.git'),
  78. `gitdir: ${gitDirPath}\n`
  79. );
  80. const directory = new Directory(workDirPath);
  81. const result = await provider.repositoryForDirectory(directory);
  82. expect(result).toBeInstanceOf(GitRepository);
  83. expect(provider.pathToRepository[result.getPath()]).toBeTruthy();
  84. expect(result.getType()).toBe('git');
  85. });
  86. });
  87. describe('when specified a Directory with a commondir file for a worktree', () => {
  88. it('returns a Promise that resolves to a GitRepository', async () => {
  89. const directory = new Directory(
  90. path.join(
  91. __dirname,
  92. 'fixtures',
  93. 'git',
  94. 'master.git',
  95. 'worktrees',
  96. 'worktree-dir'
  97. )
  98. );
  99. const result = await provider.repositoryForDirectory(directory);
  100. expect(result).toBeInstanceOf(GitRepository);
  101. expect(provider.pathToRepository[result.getPath()]).toBeTruthy();
  102. expect(result.getType()).toBe('git');
  103. });
  104. });
  105. describe('when specified a Directory without exists()', () => {
  106. let directory;
  107. beforeEach(() => {
  108. // An implementation of Directory that does not implement existsSync().
  109. const subdirectory = {};
  110. directory = {
  111. getSubdirectory() {},
  112. isRoot() {
  113. return true;
  114. }
  115. };
  116. spyOn(directory, 'getSubdirectory').andReturn(subdirectory);
  117. });
  118. it('returns a Promise that resolves to null', async () => {
  119. const repo = await provider.repositoryForDirectory(directory);
  120. expect(repo).toBe(null);
  121. expect(directory.getSubdirectory).toHaveBeenCalledWith('.git');
  122. });
  123. });
  124. });
  125. describe('.repositoryForDirectorySync(directory)', () => {
  126. describe('when specified a Directory with a Git repository', () => {
  127. it('resolves with a GitRepository', async () => {
  128. const directory = new Directory(
  129. path.join(__dirname, 'fixtures', 'git', 'master.git')
  130. );
  131. const result = provider.repositoryForDirectorySync(directory);
  132. expect(result).toBeInstanceOf(GitRepository);
  133. expect(provider.pathToRepository[result.getPath()]).toBeTruthy();
  134. expect(result.getType()).toBe('git');
  135. // Refresh should be started
  136. await new Promise(resolve => result.onDidChangeStatuses(resolve));
  137. });
  138. it('resolves with the same GitRepository for different Directory objects in the same repo', () => {
  139. const firstRepo = provider.repositoryForDirectorySync(
  140. new Directory(path.join(__dirname, 'fixtures', 'git', 'master.git'))
  141. );
  142. const secondRepo = provider.repositoryForDirectorySync(
  143. new Directory(
  144. path.join(__dirname, 'fixtures', 'git', 'master.git', 'objects')
  145. )
  146. );
  147. expect(firstRepo).toBeInstanceOf(GitRepository);
  148. expect(firstRepo).toBe(secondRepo);
  149. });
  150. });
  151. describe('when specified a Directory without a Git repository', () => {
  152. it('resolves with null', () => {
  153. const directory = new Directory(temp.mkdirSync('dir'));
  154. const repo = provider.repositoryForDirectorySync(directory);
  155. expect(repo).toBe(null);
  156. });
  157. });
  158. describe('when specified a Directory with an invalid Git repository', () => {
  159. it('resolves with null', () => {
  160. const dirPath = temp.mkdirSync('dir');
  161. fs.writeFileSync(path.join(dirPath, '.git', 'objects'), '');
  162. fs.writeFileSync(path.join(dirPath, '.git', 'HEAD'), '');
  163. fs.writeFileSync(path.join(dirPath, '.git', 'refs'), '');
  164. const directory = new Directory(dirPath);
  165. const repo = provider.repositoryForDirectorySync(directory);
  166. expect(repo).toBe(null);
  167. });
  168. });
  169. describe('when specified a Directory with a valid gitfile-linked repository', () => {
  170. it('returns a Promise that resolves to a GitRepository', () => {
  171. const gitDirPath = path.join(
  172. __dirname,
  173. 'fixtures',
  174. 'git',
  175. 'master.git'
  176. );
  177. const workDirPath = temp.mkdirSync('git-workdir');
  178. fs.writeFileSync(
  179. path.join(workDirPath, '.git'),
  180. `gitdir: ${gitDirPath}\n`
  181. );
  182. const directory = new Directory(workDirPath);
  183. const result = provider.repositoryForDirectorySync(directory);
  184. expect(result).toBeInstanceOf(GitRepository);
  185. expect(provider.pathToRepository[result.getPath()]).toBeTruthy();
  186. expect(result.getType()).toBe('git');
  187. });
  188. });
  189. describe('when specified a Directory with a commondir file for a worktree', () => {
  190. it('returns a Promise that resolves to a GitRepository', () => {
  191. const directory = new Directory(
  192. path.join(
  193. __dirname,
  194. 'fixtures',
  195. 'git',
  196. 'master.git',
  197. 'worktrees',
  198. 'worktree-dir'
  199. )
  200. );
  201. const result = provider.repositoryForDirectorySync(directory);
  202. expect(result).toBeInstanceOf(GitRepository);
  203. expect(provider.pathToRepository[result.getPath()]).toBeTruthy();
  204. expect(result.getType()).toBe('git');
  205. });
  206. });
  207. describe('when specified a Directory without existsSync()', () => {
  208. let directory;
  209. beforeEach(() => {
  210. // An implementation of Directory that does not implement existsSync().
  211. const subdirectory = {};
  212. directory = {
  213. getSubdirectory() {},
  214. isRoot() {
  215. return true;
  216. }
  217. };
  218. spyOn(directory, 'getSubdirectory').andReturn(subdirectory);
  219. });
  220. it('returns null', () => {
  221. const repo = provider.repositoryForDirectorySync(directory);
  222. expect(repo).toBe(null);
  223. expect(directory.getSubdirectory).toHaveBeenCalledWith('.git');
  224. });
  225. });
  226. });
  227. });