git-drive 0.1.5 → 0.1.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (93) hide show
  1. package/dist/__tests__/commands/init.test.js +123 -0
  2. package/dist/__tests__/commands/list.test.js +91 -0
  3. package/dist/__tests__/commands/push.test.js +128 -0
  4. package/dist/__tests__/commands/restore.test.js +99 -0
  5. package/dist/__tests__/commands/status.test.js +151 -0
  6. package/dist/__tests__/config.test.js +150 -0
  7. package/dist/__tests__/e2e.test.js +107 -0
  8. package/dist/__tests__/errors.test.js +56 -0
  9. package/dist/__tests__/git.test.js +184 -0
  10. package/dist/__tests__/server.test.js +310 -0
  11. package/dist/commands/archive.js +32 -0
  12. package/dist/commands/init.js +55 -0
  13. package/dist/commands/link.js +175 -0
  14. package/dist/commands/list.js +83 -0
  15. package/dist/commands/push.js +112 -0
  16. package/dist/commands/restore.js +30 -0
  17. package/dist/commands/status.js +116 -0
  18. package/dist/config.js +62 -0
  19. package/dist/errors.js +30 -0
  20. package/dist/git.js +67 -0
  21. package/dist/index.js +108 -0
  22. package/dist/server.js +535 -0
  23. package/package.json +55 -20
  24. package/.github/workflows/ci.yml +0 -77
  25. package/.planning/codebase/ARCHITECTURE.md +0 -151
  26. package/.planning/codebase/CONCERNS.md +0 -191
  27. package/.planning/codebase/CONVENTIONS.md +0 -169
  28. package/.planning/codebase/INTEGRATIONS.md +0 -94
  29. package/.planning/codebase/STACK.md +0 -77
  30. package/.planning/codebase/STRUCTURE.md +0 -157
  31. package/.planning/codebase/TESTING.md +0 -156
  32. package/Dockerfile.cli +0 -30
  33. package/Dockerfile.server +0 -32
  34. package/README.md +0 -121
  35. package/docker-compose.yml +0 -48
  36. package/packages/cli/Dockerfile +0 -26
  37. package/packages/cli/jest.config.js +0 -26
  38. package/packages/cli/package.json +0 -65
  39. package/packages/cli/src/__tests__/commands/init.test.ts +0 -154
  40. package/packages/cli/src/__tests__/commands/list.test.ts +0 -118
  41. package/packages/cli/src/__tests__/commands/push.test.ts +0 -155
  42. package/packages/cli/src/__tests__/commands/restore.test.ts +0 -134
  43. package/packages/cli/src/__tests__/commands/status.test.ts +0 -195
  44. package/packages/cli/src/__tests__/config.test.ts +0 -198
  45. package/packages/cli/src/__tests__/e2e.test.ts +0 -125
  46. package/packages/cli/src/__tests__/errors.test.ts +0 -66
  47. package/packages/cli/src/__tests__/git.test.ts +0 -226
  48. package/packages/cli/src/__tests__/server.test.ts +0 -368
  49. package/packages/cli/src/commands/archive.ts +0 -39
  50. package/packages/cli/src/commands/init.ts +0 -64
  51. package/packages/cli/src/commands/link.ts +0 -151
  52. package/packages/cli/src/commands/list.ts +0 -94
  53. package/packages/cli/src/commands/push.ts +0 -77
  54. package/packages/cli/src/commands/restore.ts +0 -36
  55. package/packages/cli/src/commands/status.ts +0 -127
  56. package/packages/cli/src/config.ts +0 -73
  57. package/packages/cli/src/errors.ts +0 -23
  58. package/packages/cli/src/git.ts +0 -55
  59. package/packages/cli/src/index.ts +0 -122
  60. package/packages/cli/src/server.ts +0 -573
  61. package/packages/cli/tsconfig.json +0 -13
  62. package/packages/git-drive-docker/package.json +0 -15
  63. package/packages/server/package.json +0 -44
  64. package/packages/server/src/index.ts +0 -569
  65. package/packages/server/tsconfig.json +0 -9
  66. package/packages/ui/README.md +0 -73
  67. package/packages/ui/eslint.config.js +0 -23
  68. package/packages/ui/index.html +0 -13
  69. package/packages/ui/package.json +0 -52
  70. package/packages/ui/postcss.config.js +0 -6
  71. package/packages/ui/public/vite.svg +0 -1
  72. package/packages/ui/src/App.css +0 -23
  73. package/packages/ui/src/App.test.tsx +0 -242
  74. package/packages/ui/src/App.tsx +0 -755
  75. package/packages/ui/src/assets/react.svg +0 -8
  76. package/packages/ui/src/assets/vite.svg +0 -3
  77. package/packages/ui/src/index.css +0 -37
  78. package/packages/ui/src/main.tsx +0 -14
  79. package/packages/ui/src/test/setup.ts +0 -1
  80. package/packages/ui/tailwind.config.js +0 -11
  81. package/packages/ui/tsconfig.app.json +0 -28
  82. package/packages/ui/tsconfig.json +0 -26
  83. package/packages/ui/tsconfig.node.json +0 -12
  84. package/packages/ui/vite.config.ts +0 -7
  85. package/packages/ui/vitest.config.ts +0 -20
  86. package/pnpm-workspace.yaml +0 -4
  87. package/rewrite_app.js +0 -731
  88. package/tsconfig.json +0 -14
  89. /package/{packages/cli/ui → ui}/assets/index-Br8xQbJz.js +0 -0
  90. /package/{packages/cli/ui → ui}/assets/index-Cc2q1t5k.js +0 -0
  91. /package/{packages/cli/ui → ui}/assets/index-DrL7ojPA.css +0 -0
  92. /package/{packages/cli/ui → ui}/index.html +0 -0
  93. /package/{packages/cli/ui → ui}/vite.svg +0 -0
@@ -1,154 +0,0 @@
1
- import { init } from '../../commands/init.js';
2
- import { GitDriveError } from '../../errors.js';
3
- import { vol } from 'memfs';
4
-
5
- // Mock fs and path modules
6
- jest.mock('fs', () => {
7
- const { fs } = require('memfs');
8
- return fs;
9
- });
10
-
11
- // Mock prompts
12
- jest.mock('prompts', () => ({
13
- __esModule: true,
14
- default: jest.fn(),
15
- }));
16
-
17
- // Mock config
18
- jest.mock('../../config.js', () => ({
19
- saveConfig: jest.fn(),
20
- getDriveStorePath: jest.fn((drivePath: string) => `${drivePath}/.git-drive`),
21
- }));
22
-
23
- // Mock git
24
- jest.mock('../../git.js', () => ({
25
- listDrives: jest.fn(),
26
- }));
27
-
28
- import prompts from 'prompts';
29
- import { listDrives } from '../../git.js';
30
- import { saveConfig, getDriveStorePath } from '../../config.js';
31
-
32
- const mockPrompts = prompts as unknown as jest.Mock;
33
- const mockListDrives = listDrives as jest.Mock;
34
- const mockSaveConfig = saveConfig as jest.Mock;
35
- const mockGetDriveStorePath = getDriveStorePath as jest.Mock;
36
-
37
- describe('init command', () => {
38
- let consoleSpy: jest.SpyInstance;
39
-
40
- beforeEach(() => {
41
- jest.clearAllMocks();
42
- vol.reset();
43
- consoleSpy = jest.spyOn(console, 'log').mockImplementation();
44
- mockGetDriveStorePath.mockImplementation((drivePath: string) => `${drivePath}/.git-drive`);
45
- });
46
-
47
- afterEach(() => {
48
- consoleSpy.mockRestore();
49
- });
50
-
51
- describe('with path argument', () => {
52
- it('should initialize git-drive on specified path', async () => {
53
- const drivePath = '/Volumes/TestDrive';
54
- vol.fromJSON({
55
- [drivePath]: '',
56
- });
57
-
58
- await init([drivePath]);
59
-
60
- expect(mockSaveConfig).toHaveBeenCalledWith({ drivePath: expect.stringContaining('TestDrive') });
61
- expect(consoleSpy).toHaveBeenCalledWith(expect.stringContaining('Git Drive initialized'));
62
- });
63
-
64
- it('should throw error if path does not exist', async () => {
65
- await expect(init(['/Volumes/NonExistent'])).rejects.toThrow(GitDriveError);
66
- await expect(init(['/Volumes/NonExistent'])).rejects.toThrow('Path not found');
67
- });
68
-
69
- it('should throw error if path is not a directory', async () => {
70
- vol.fromJSON({
71
- '/Volumes/SomeFile': 'file content',
72
- });
73
-
74
- await expect(init(['/Volumes/SomeFile'])).rejects.toThrow('Path is not a directory');
75
- });
76
-
77
- it('should resolve relative paths', async () => {
78
- vol.fromJSON({
79
- '/current/dir/TestDrive': '',
80
- });
81
-
82
- // Mock cwd to return a specific directory
83
- const originalCwd = process.cwd;
84
- process.cwd = jest.fn(() => '/current/dir');
85
-
86
- await init(['./TestDrive']);
87
-
88
- expect(mockSaveConfig).toHaveBeenCalled();
89
-
90
- process.cwd = originalCwd;
91
- });
92
- });
93
-
94
- describe('without path argument (interactive)', () => {
95
- it('should throw error when no drives found', async () => {
96
- mockListDrives.mockResolvedValue([]);
97
-
98
- await expect(init([])).rejects.toThrow('No external drives found');
99
- });
100
-
101
- it('should prompt user to select a drive', async () => {
102
- mockListDrives.mockResolvedValue([
103
- { mounted: '/Volumes/Drive1', filesystem: 'Drive1', blocks: 1000000, available: 500000 },
104
- { mounted: '/Volumes/Drive2', filesystem: 'Drive2', blocks: 2000000, available: 1000000 },
105
- ]);
106
-
107
- mockPrompts.mockResolvedValue({
108
- selectedDrive: '/Volumes/Drive1',
109
- });
110
-
111
- vol.fromJSON({
112
- '/Volumes/Drive1': '',
113
- });
114
-
115
- await init([]);
116
-
117
- expect(mockPrompts).toHaveBeenCalledWith(
118
- expect.objectContaining({
119
- type: 'select',
120
- name: 'selectedDrive',
121
- })
122
- );
123
- });
124
-
125
- it('should handle user cancellation', async () => {
126
- mockListDrives.mockResolvedValue([
127
- { mounted: '/Volumes/Drive1', filesystem: 'Drive1', blocks: 1000000, available: 500000 },
128
- ]);
129
-
130
- mockPrompts.mockResolvedValue({
131
- selectedDrive: undefined,
132
- });
133
-
134
- await init([]);
135
-
136
- expect(consoleSpy).toHaveBeenCalledWith('Operation cancelled.');
137
- expect(mockSaveConfig).not.toHaveBeenCalled();
138
- });
139
- });
140
-
141
- describe('store directory creation', () => {
142
- it('should create .git-drive directory if it does not exist', async () => {
143
- const drivePath = '/Volumes/TestDrive';
144
- vol.fromJSON({
145
- [drivePath]: '',
146
- });
147
-
148
- await init([drivePath]);
149
-
150
- // The store path should have been requested
151
- expect(mockGetDriveStorePath).toHaveBeenCalled();
152
- });
153
- });
154
- });
@@ -1,118 +0,0 @@
1
- import { vol } from 'memfs';
2
-
3
- // Mock fs
4
- jest.mock('fs', () => {
5
- const { fs } = require('memfs');
6
- return fs;
7
- });
8
-
9
- // Mock node-disk-info
10
- jest.mock('node-disk-info', () => ({
11
- getDiskInfo: jest.fn(),
12
- }));
13
-
14
- // Mock server
15
- jest.mock('../../server.js', () => ({
16
- ensureServerRunning: jest.fn(),
17
- }));
18
-
19
- // Mock os
20
- jest.mock('os', () => ({
21
- homedir: () => '/home/testuser',
22
- }));
23
-
24
- import { getDiskInfo } from 'node-disk-info';
25
- import { list } from '../../commands/list.js';
26
-
27
- const mockGetDiskInfo = getDiskInfo as jest.Mock;
28
-
29
- describe('list command', () => {
30
- let consoleSpy: jest.SpyInstance;
31
- const originalPlatform = process.platform;
32
-
33
- beforeEach(() => {
34
- jest.clearAllMocks();
35
- vol.reset();
36
- consoleSpy = jest.spyOn(console, 'log').mockImplementation();
37
- Object.defineProperty(process, 'platform', { value: 'darwin', writable: true });
38
- });
39
-
40
- afterEach(() => {
41
- consoleSpy.mockRestore();
42
- Object.defineProperty(process, 'platform', { value: originalPlatform, writable: true });
43
- });
44
-
45
- it('should display no drives message when no external drives found', async () => {
46
- mockGetDiskInfo.mockResolvedValue([]);
47
-
48
- vol.fromJSON({
49
- '/home/testuser/.config/git-drive/links.json': '{}',
50
- });
51
-
52
- await list([]);
53
-
54
- expect(consoleSpy).toHaveBeenCalledWith(expect.stringContaining('No external drives detected'));
55
- });
56
-
57
- it('should list connected drives with git-drive status', async () => {
58
- mockGetDiskInfo.mockResolvedValue([
59
- { mounted: '/Volumes/MyUSB', filesystem: 'MyUSB', blocks: 32000000, available: 16000000 },
60
- { mounted: '/Volumes/External', filesystem: 'External', blocks: 1000000000, available: 500000000 },
61
- ]);
62
-
63
- vol.fromJSON({
64
- '/home/testuser/.config/git-drive/links.json': '{}',
65
- '/Volumes/MyUSB/.git-drive/my-project.git/HEAD': '',
66
- '/Volumes/External': '',
67
- });
68
-
69
- await list([]);
70
-
71
- expect(consoleSpy).toHaveBeenCalledWith(expect.stringContaining('/Volumes/MyUSB'));
72
- expect(consoleSpy).toHaveBeenCalledWith(expect.stringContaining('/Volumes/External'));
73
- });
74
-
75
- it('should count repositories on initialized drives', async () => {
76
- mockGetDiskInfo.mockResolvedValue([
77
- { mounted: '/Volumes/MyUSB', filesystem: 'MyUSB', blocks: 32000000, available: 16000000 },
78
- ]);
79
-
80
- vol.fromJSON({
81
- '/home/testuser/.config/git-drive/links.json': '{}',
82
- '/Volumes/MyUSB/.git-drive/project1.git/HEAD': '',
83
- '/Volumes/MyUSB/.git-drive/project2.git/HEAD': '',
84
- '/Volumes/MyUSB/.git-drive/project3.git/HEAD': '',
85
- });
86
-
87
- await list([]);
88
-
89
- expect(consoleSpy).toHaveBeenCalledWith(expect.stringContaining('Repositories: 3'));
90
- });
91
-
92
- it('should display drive size in GB', async () => {
93
- mockGetDiskInfo.mockResolvedValue([
94
- { mounted: '/Volumes/MyUSB', filesystem: 'MyUSB', blocks: 97656250, available: 50000000 },
95
- ]);
96
-
97
- vol.fromJSON({
98
- '/home/testuser/.config/git-drive/links.json': '{}',
99
- '/Volumes/MyUSB': '',
100
- });
101
-
102
- await list([]);
103
-
104
- expect(consoleSpy).toHaveBeenCalledWith(expect.stringContaining('GB'));
105
- });
106
-
107
- it('should handle errors when detecting drives', async () => {
108
- mockGetDiskInfo.mockRejectedValue(new Error('Failed to detect drives'));
109
-
110
- vol.fromJSON({
111
- '/home/testuser/.config/git-drive/links.json': '{}',
112
- });
113
-
114
- await list([]);
115
-
116
- expect(consoleSpy).toHaveBeenCalledWith('Error detecting drives:', expect.any(Error));
117
- });
118
- });
@@ -1,155 +0,0 @@
1
- import { push } from '../../commands/push.js';
2
- import { GitDriveError } from '../../errors.js';
3
- import { vol } from 'memfs';
4
-
5
- // Mock fs
6
- jest.mock('fs', () => {
7
- const { fs } = require('memfs');
8
- return fs;
9
- });
10
-
11
- // Mock prompts
12
- jest.mock('prompts', () => ({
13
- __esModule: true,
14
- default: jest.fn(),
15
- }));
16
-
17
- // Mock git
18
- jest.mock('../../git.js', () => ({
19
- git: jest.fn(),
20
- getRemoteUrl: jest.fn(),
21
- isGitRepo: jest.fn(),
22
- }));
23
-
24
- // Mock server
25
- jest.mock('../../server.js', () => ({
26
- ensureServerRunning: jest.fn(),
27
- }));
28
-
29
- import prompts from 'prompts';
30
- import { git, getRemoteUrl, isGitRepo } from '../../git.js';
31
-
32
- const mockPrompts = prompts as unknown as jest.Mock;
33
- const mockGit = git as jest.Mock;
34
- const mockGetRemoteUrl = getRemoteUrl as jest.Mock;
35
- const mockIsGitRepo = isGitRepo as jest.Mock;
36
-
37
- describe('push command', () => {
38
- let consoleSpy: jest.SpyInstance;
39
-
40
- beforeEach(() => {
41
- jest.clearAllMocks();
42
- vol.reset();
43
- consoleSpy = jest.spyOn(console, 'log').mockImplementation();
44
- mockIsGitRepo.mockReturnValue(true);
45
- mockGetRemoteUrl.mockReturnValue('/Volumes/TestDrive/.git-drive/my-repo.git');
46
- mockGit.mockImplementation((cmd: string) => {
47
- if (cmd.includes('branch --show-current')) return 'main';
48
- return '';
49
- });
50
- });
51
-
52
- afterEach(() => {
53
- consoleSpy.mockRestore();
54
- });
55
-
56
- it('should throw error when not in a git repository', async () => {
57
- mockIsGitRepo.mockReturnValue(false);
58
-
59
- await expect(push([])).rejects.toThrow(GitDriveError);
60
- await expect(push([])).rejects.toThrow('Not in a git repository');
61
- });
62
-
63
- it('should throw error when no git-drive linked', async () => {
64
- mockIsGitRepo.mockReturnValue(true);
65
- mockGetRemoteUrl.mockReturnValue(null);
66
-
67
- await expect(push([])).rejects.toThrow("No git-drive linked for this project");
68
- });
69
-
70
- describe('push modes', () => {
71
- beforeEach(() => {
72
- vol.fromJSON({
73
- '/Volumes/TestDrive/.git-drive/my-repo.git/HEAD': '',
74
- });
75
- });
76
-
77
- it('should push current branch with --current flag', async () => {
78
- await push(['--current']);
79
-
80
- expect(mockGit).toHaveBeenCalledWith(expect.stringContaining('push gd main'));
81
- expect(consoleSpy).toHaveBeenCalledWith(expect.stringContaining('Successfully pushed'));
82
- });
83
-
84
- it('should push all branches and tags with --all flag', async () => {
85
- await push(['--all']);
86
-
87
- expect(mockGit).toHaveBeenCalledWith('push gd --all');
88
- expect(mockGit).toHaveBeenCalledWith('push gd --tags');
89
- expect(consoleSpy).toHaveBeenCalledWith(expect.stringContaining('all branches and tags'));
90
- });
91
-
92
- it('should prompt for push mode when no flags provided', async () => {
93
- mockPrompts.mockResolvedValue({ pushMode: 'current' });
94
-
95
- await push([]);
96
-
97
- expect(mockPrompts).toHaveBeenCalledWith(
98
- expect.objectContaining({
99
- type: 'select',
100
- name: 'pushMode',
101
- })
102
- );
103
- });
104
-
105
- it('should handle user cancellation in interactive mode', async () => {
106
- mockPrompts.mockResolvedValue({ pushMode: undefined });
107
-
108
- await push([]);
109
-
110
- // Should not have pushed anything beyond the prompt
111
- expect(mockGit).not.toHaveBeenCalledWith(expect.stringContaining('push gd'));
112
- });
113
- });
114
-
115
- describe('pushlog', () => {
116
- it('should write pushlog on successful push', async () => {
117
- vol.fromJSON({
118
- '/Volumes/TestDrive/.git-drive/my-repo.git/HEAD': '',
119
- });
120
-
121
- await push(['--current']);
122
-
123
- // Check that the pushlog file was created
124
- const files = vol.toJSON();
125
- const pushlogPath = '/Volumes/TestDrive/.git-drive/my-repo.git/git-drive-pushlog.json';
126
- // The pushlog should exist if the remote URL path exists
127
- // This is tested indirectly through the code path
128
- });
129
-
130
- it('should handle pushlog write errors silently', async () => {
131
- // Create a scenario where writing the pushlog would fail
132
- vol.fromJSON({
133
- '/Volumes/TestDrive/.git-drive/my-repo.git/HEAD': '',
134
- });
135
-
136
- // This should not throw even if pushlog writing fails
137
- await expect(push(['--current'])).resolves.not.toThrow();
138
- });
139
- });
140
-
141
- describe('error handling', () => {
142
- it('should throw GitDriveError when git push fails', async () => {
143
- vol.fromJSON({
144
- '/Volumes/TestDrive/.git-drive/my-repo.git/HEAD': '',
145
- });
146
-
147
- mockGit.mockImplementation((cmd: string) => {
148
- if (cmd.includes('branch --show-current')) return 'main';
149
- throw new Error('fatal: failed to push');
150
- });
151
-
152
- await expect(push(['--current'])).rejects.toThrow(GitDriveError);
153
- });
154
- });
155
- });
@@ -1,134 +0,0 @@
1
- import { restore } from '../../commands/restore.js';
2
- import { GitDriveError } from '../../errors.js';
3
- import { vol } from 'memfs';
4
-
5
- // Mock fs
6
- jest.mock('fs', () => {
7
- const { fs } = require('memfs');
8
- return fs;
9
- });
10
-
11
- // Mock config
12
- jest.mock('../../config.js', () => ({
13
- requireConfig: jest.fn(),
14
- assertDriveMounted: jest.fn(),
15
- getDriveStorePath: jest.fn((drivePath: string) => `${drivePath}/.git-drive`),
16
- }));
17
-
18
- // Mock git
19
- jest.mock('../../git.js', () => ({
20
- git: jest.fn(),
21
- }));
22
-
23
- // Mock server
24
- jest.mock('../../server.js', () => ({
25
- ensureServerRunning: jest.fn(),
26
- }));
27
-
28
- import { git } from '../../git.js';
29
- import { requireConfig, assertDriveMounted } from '../../config.js';
30
-
31
- const mockGit = git as jest.Mock;
32
- const mockRequireConfig = requireConfig as jest.Mock;
33
- const mockAssertDriveMounted = assertDriveMounted as jest.Mock;
34
-
35
- describe('restore command', () => {
36
- let consoleSpy: jest.SpyInstance;
37
-
38
- beforeEach(() => {
39
- jest.clearAllMocks();
40
- vol.reset();
41
- consoleSpy = jest.spyOn(console, 'log').mockImplementation();
42
- mockRequireConfig.mockReturnValue({ drivePath: '/Volumes/MyUSB' });
43
- mockAssertDriveMounted.mockImplementation(() => {});
44
- mockGit.mockImplementation(() => {});
45
- });
46
-
47
- afterEach(() => {
48
- consoleSpy.mockRestore();
49
- });
50
-
51
- it('should throw error when no project name provided', () => {
52
- expect(() => restore([])).toThrow(GitDriveError);
53
- expect(() => restore([])).toThrow('Usage: git drive restore <project-name> [target-dir]');
54
- });
55
-
56
- it('should throw error when project not found on drive', () => {
57
- vol.fromJSON({
58
- '/Volumes/MyUSB/.git-drive': '',
59
- });
60
-
61
- expect(() => restore(['nonexistent-project'])).toThrow(GitDriveError);
62
- expect(() => restore(['nonexistent-project'])).toThrow("Project 'nonexistent-project' not found on drive.");
63
- });
64
-
65
- it('should throw error when target directory already exists', () => {
66
- vol.fromJSON({
67
- '/Volumes/MyUSB/.git-drive/my-project.git/HEAD': '',
68
- '/home/user/my-project': '',
69
- });
70
-
71
- expect(() => restore(['my-project', '/home/user/my-project'])).toThrow(GitDriveError);
72
- expect(() => restore(['my-project', '/home/user/my-project'])).toThrow('Directory already exists');
73
- });
74
-
75
- it('should clone the bare repo to target directory', () => {
76
- vol.fromJSON({
77
- '/Volumes/MyUSB/.git-drive/my-project.git/HEAD': '',
78
- });
79
-
80
- restore(['my-project', '/home/user/restored-project']);
81
-
82
- expect(mockGit).toHaveBeenCalledWith(
83
- expect.stringContaining('clone /Volumes/MyUSB/.git-drive/my-project.git')
84
- );
85
- });
86
-
87
- it('should rename origin remote to drive', () => {
88
- vol.fromJSON({
89
- '/Volumes/MyUSB/.git-drive/my-project.git/HEAD': '',
90
- });
91
-
92
- restore(['my-project', '/home/user/restored-project']);
93
-
94
- expect(mockGit).toHaveBeenCalledWith(
95
- expect.stringContaining('remote rename origin drive'),
96
- expect.any(String)
97
- );
98
- });
99
-
100
- it('should use project name as target directory if not specified', () => {
101
- vol.fromJSON({
102
- '/Volumes/MyUSB/.git-drive/my-project.git/HEAD': '',
103
- });
104
-
105
- restore(['my-project']);
106
-
107
- // Should call git clone with the project name
108
- expect(mockGit).toHaveBeenCalledWith(
109
- expect.stringMatching(/clone.*my-project\.git/),
110
- undefined
111
- );
112
- });
113
-
114
- it('should log success message', () => {
115
- vol.fromJSON({
116
- '/Volumes/MyUSB/.git-drive/my-project.git/HEAD': '',
117
- });
118
-
119
- restore(['my-project']);
120
-
121
- expect(consoleSpy).toHaveBeenCalledWith(expect.stringContaining('Restored'));
122
- expect(consoleSpy).toHaveBeenCalledWith(expect.stringContaining('my-project'));
123
- });
124
-
125
- it('should work with custom target directory', () => {
126
- vol.fromJSON({
127
- '/Volumes/MyUSB/.git-drive/my-project.git/HEAD': '',
128
- });
129
-
130
- restore(['my-project', '/custom/target']);
131
-
132
- expect(consoleSpy).toHaveBeenCalledWith(expect.stringContaining('/custom/target'));
133
- });
134
- });