simple-vcs 1.0.0__py3-none-any.whl

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.
simple_vcs/__init__.py ADDED
@@ -0,0 +1,10 @@
1
+ """
2
+ SimpleVCS - A simple version control system
3
+ """
4
+
5
+ __version__ = "1.0.0"
6
+ __author__ = "Your Name"
7
+
8
+ from .core import SimpleVCS
9
+
10
+ __all__ = ["SimpleVCS"]
simple_vcs/cli.py ADDED
@@ -0,0 +1,54 @@
1
+ import click
2
+ from .core import SimpleVCS
3
+
4
+ @click.group()
5
+ @click.version_option()
6
+ def main():
7
+ """SimpleVCS - A simple version control system"""
8
+ pass
9
+
10
+ @main.command()
11
+ @click.option('--path', default='.', help='Repository path')
12
+ def init(path):
13
+ """Initialize a new repository"""
14
+ vcs = SimpleVCS(path)
15
+ vcs.init_repo()
16
+
17
+ @main.command()
18
+ @click.argument('files', nargs=-1, required=True)
19
+ def add(files):
20
+ """Add files to staging area"""
21
+ vcs = SimpleVCS()
22
+ for file in files:
23
+ vcs.add_file(file)
24
+
25
+ @main.command()
26
+ @click.option('-m', '--message', help='Commit message')
27
+ def commit(message):
28
+ """Commit staged changes"""
29
+ vcs = SimpleVCS()
30
+ vcs.commit(message)
31
+
32
+ @main.command()
33
+ @click.option('--c1', type=int, help='First commit ID')
34
+ @click.option('--c2', type=int, help='Second commit ID')
35
+ def diff(c1, c2):
36
+ """Show differences between commits"""
37
+ vcs = SimpleVCS()
38
+ vcs.show_diff(c1, c2)
39
+
40
+ @main.command()
41
+ @click.option('--limit', type=int, help='Limit number of commits to show')
42
+ def log(limit):
43
+ """Show commit history"""
44
+ vcs = SimpleVCS()
45
+ vcs.show_log(limit)
46
+
47
+ @main.command()
48
+ def status():
49
+ """Show repository status"""
50
+ vcs = SimpleVCS()
51
+ vcs.status()
52
+
53
+ if __name__ == '__main__':
54
+ main()
simple_vcs/core.py ADDED
@@ -0,0 +1,276 @@
1
+ import os
2
+ import json
3
+ import hashlib
4
+ import shutil
5
+ import time
6
+ from datetime import datetime
7
+ from pathlib import Path
8
+ from typing import Dict, List, Optional, Tuple
9
+
10
+ class SimpleVCS:
11
+ """Simple Version Control System core functionality"""
12
+
13
+ def __init__(self, repo_path: str = "."):
14
+ self.repo_path = Path(repo_path).resolve()
15
+ self.svcs_dir = self.repo_path / ".svcs"
16
+ self.objects_dir = self.svcs_dir / "objects"
17
+ self.commits_file = self.svcs_dir / "commits.json"
18
+ self.staging_file = self.svcs_dir / "staging.json"
19
+ self.head_file = self.svcs_dir / "HEAD"
20
+
21
+ def init_repo(self) -> bool:
22
+ """Initialize a new repository"""
23
+ if self.svcs_dir.exists():
24
+ print(f"Repository already exists at {self.repo_path}")
25
+ return False
26
+
27
+ # Create directory structure
28
+ self.svcs_dir.mkdir()
29
+ self.objects_dir.mkdir()
30
+
31
+ # Initialize files
32
+ self._write_json(self.commits_file, [])
33
+ self._write_json(self.staging_file, {})
34
+ self.head_file.write_text("0") # Start with commit 0
35
+
36
+ print(f"Initialized empty SimpleVCS repository at {self.repo_path}")
37
+ return True
38
+
39
+ def add_file(self, file_path: str) -> bool:
40
+ """Add a file to staging area"""
41
+ if not self._check_repo():
42
+ return False
43
+
44
+ file_path = Path(file_path).resolve() # Convert to absolute path
45
+ if not file_path.exists():
46
+ print(f"File {file_path} does not exist")
47
+ return False
48
+
49
+ if not file_path.is_file():
50
+ print(f"{file_path} is not a file")
51
+ return False
52
+
53
+ # Check if file is within repository
54
+ try:
55
+ relative_path = file_path.relative_to(self.repo_path)
56
+ except ValueError:
57
+ print(f"File {file_path} is not within the repository")
58
+ return False
59
+
60
+ # Calculate file hash
61
+ file_hash = self._calculate_file_hash(file_path)
62
+
63
+ # Store file content in objects
64
+ self._store_object(file_hash, file_path.read_bytes())
65
+
66
+ # Add to staging
67
+ staging = self._read_json(self.staging_file)
68
+ staging[str(relative_path)] = {
69
+ "hash": file_hash,
70
+ "size": file_path.stat().st_size,
71
+ "modified": file_path.stat().st_mtime
72
+ }
73
+ self._write_json(self.staging_file, staging)
74
+
75
+ print(f"Added {file_path.name} to staging area")
76
+ return True
77
+
78
+ def commit(self, message: Optional[str] = None) -> bool:
79
+ """Commit staged changes"""
80
+ if not self._check_repo():
81
+ return False
82
+
83
+ staging = self._read_json(self.staging_file)
84
+ if not staging:
85
+ print("No changes to commit")
86
+ return False
87
+
88
+ # Create commit object
89
+ commit = {
90
+ "id": len(self._read_json(self.commits_file)) + 1,
91
+ "message": message or f"Commit at {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}",
92
+ "timestamp": time.time(),
93
+ "files": staging.copy(),
94
+ "parent": self._get_current_commit_id()
95
+ }
96
+
97
+ # Save commit
98
+ commits = self._read_json(self.commits_file)
99
+ commits.append(commit)
100
+ self._write_json(self.commits_file, commits)
101
+
102
+ # Update HEAD
103
+ self.head_file.write_text(str(commit["id"]))
104
+
105
+ # Clear staging
106
+ self._write_json(self.staging_file, {})
107
+
108
+ print(f"Committed changes with ID: {commit['id']}")
109
+ print(f"Message: {commit['message']}")
110
+ return True
111
+
112
+ def show_diff(self, commit_id1: Optional[int] = None, commit_id2: Optional[int] = None) -> bool:
113
+ """Show differences between commits"""
114
+ if not self._check_repo():
115
+ return False
116
+
117
+ commits = self._read_json(self.commits_file)
118
+ if not commits:
119
+ print("No commits found")
120
+ return False
121
+
122
+ # Default to comparing last two commits
123
+ if commit_id1 is None and commit_id2 is None:
124
+ if len(commits) < 2:
125
+ print("Need at least 2 commits to show diff")
126
+ return False
127
+ commit1 = commits[-2]
128
+ commit2 = commits[-1]
129
+ else:
130
+ commit1 = self._get_commit_by_id(commit_id1 or (len(commits) - 1))
131
+ commit2 = self._get_commit_by_id(commit_id2 or len(commits))
132
+
133
+ if not commit1 or not commit2:
134
+ print("Invalid commit IDs")
135
+ return False
136
+
137
+ print(f"\nDifferences between commit {commit1['id']} and {commit2['id']}:")
138
+ print("-" * 50)
139
+
140
+ files1 = set(commit1["files"].keys())
141
+ files2 = set(commit2["files"].keys())
142
+
143
+ # New files
144
+ new_files = files2 - files1
145
+ if new_files:
146
+ print("New files:")
147
+ for file in new_files:
148
+ print(f" + {file}")
149
+
150
+ # Deleted files
151
+ deleted_files = files1 - files2
152
+ if deleted_files:
153
+ print("Deleted files:")
154
+ for file in deleted_files:
155
+ print(f" - {file}")
156
+
157
+ # Modified files
158
+ common_files = files1 & files2
159
+ modified_files = []
160
+ for file in common_files:
161
+ if commit1["files"][file]["hash"] != commit2["files"][file]["hash"]:
162
+ modified_files.append(file)
163
+
164
+ if modified_files:
165
+ print("Modified files:")
166
+ for file in modified_files:
167
+ print(f" M {file}")
168
+
169
+ if not new_files and not deleted_files and not modified_files:
170
+ print("No differences found")
171
+
172
+ return True
173
+
174
+ def show_log(self, limit: Optional[int] = None) -> bool:
175
+ """Show commit history"""
176
+ if not self._check_repo():
177
+ return False
178
+
179
+ commits = self._read_json(self.commits_file)
180
+ if not commits:
181
+ print("No commits found")
182
+ return False
183
+
184
+ commits_to_show = commits[-limit:] if limit else commits
185
+ commits_to_show.reverse() # Show newest first
186
+
187
+ print("\nCommit History:")
188
+ print("=" * 50)
189
+
190
+ for commit in commits_to_show:
191
+ print(f"Commit ID: {commit['id']}")
192
+ print(f"Date: {datetime.fromtimestamp(commit['timestamp']).strftime('%Y-%m-%d %H:%M:%S')}")
193
+ print(f"Message: {commit['message']}")
194
+ print(f"Files: {len(commit['files'])} file(s)")
195
+ if commit.get('parent'):
196
+ print(f"Parent: {commit['parent']}")
197
+ print("-" * 30)
198
+
199
+ return True
200
+
201
+ def status(self) -> bool:
202
+ """Show repository status"""
203
+ if not self._check_repo():
204
+ return False
205
+
206
+ staging = self._read_json(self.staging_file)
207
+ current_commit = self._get_current_commit()
208
+
209
+ print(f"\nRepository: {self.repo_path}")
210
+ print(f"Current commit: {current_commit['id'] if current_commit else 'None'}")
211
+
212
+ if staging:
213
+ print("\nStaged files:")
214
+ for file, info in staging.items():
215
+ print(f" {file}")
216
+ else:
217
+ print("\nNo files staged")
218
+
219
+ return True
220
+
221
+ # Helper methods
222
+ def _check_repo(self) -> bool:
223
+ """Check if repository is initialized"""
224
+ if not self.svcs_dir.exists():
225
+ print("Not a SimpleVCS repository. Run 'svcs init' first.")
226
+ return False
227
+ return True
228
+
229
+ def _calculate_file_hash(self, file_path: Path) -> str:
230
+ """Calculate SHA-256 hash of file"""
231
+ hasher = hashlib.sha256()
232
+ with open(file_path, 'rb') as f:
233
+ for chunk in iter(lambda: f.read(4096), b""):
234
+ hasher.update(chunk)
235
+ return hasher.hexdigest()
236
+
237
+ def _store_object(self, obj_hash: str, content: bytes):
238
+ """Store object in objects directory"""
239
+ obj_path = self.objects_dir / obj_hash
240
+ if not obj_path.exists():
241
+ obj_path.write_bytes(content)
242
+
243
+ def _read_json(self, file_path: Path) -> Dict:
244
+ """Read JSON file"""
245
+ if not file_path.exists():
246
+ return {}
247
+ return json.loads(file_path.read_text())
248
+
249
+ def _write_json(self, file_path: Path, data: Dict):
250
+ """Write JSON file"""
251
+ file_path.write_text(json.dumps(data, indent=2))
252
+
253
+ def _get_current_commit_id(self) -> Optional[int]:
254
+ """Get current commit ID"""
255
+ if not self.head_file.exists():
256
+ return None
257
+ try:
258
+ commit_id = int(self.head_file.read_text().strip())
259
+ return commit_id if commit_id > 0 else None
260
+ except:
261
+ return None
262
+
263
+ def _get_current_commit(self) -> Optional[Dict]:
264
+ """Get current commit object"""
265
+ commit_id = self._get_current_commit_id()
266
+ if not commit_id:
267
+ return None
268
+ return self._get_commit_by_id(commit_id)
269
+
270
+ def _get_commit_by_id(self, commit_id: int) -> Optional[Dict]:
271
+ """Get commit by ID"""
272
+ commits = self._read_json(self.commits_file)
273
+ for commit in commits:
274
+ if commit["id"] == commit_id:
275
+ return commit
276
+ return None
simple_vcs/utils.py ADDED
@@ -0,0 +1,36 @@
1
+ import os
2
+ from pathlib import Path
3
+ from typing import List
4
+
5
+ def get_all_files(directory: str, ignore_patterns: List[str] = None) -> List[str]:
6
+ """Get all files in directory, excluding ignored patterns"""
7
+ if ignore_patterns is None:
8
+ ignore_patterns = ['.svcs', '__pycache__', '.git', '.DS_Store']
9
+
10
+ files = []
11
+ for root, dirs, filenames in os.walk(directory):
12
+ # Remove ignored directories
13
+ dirs[:] = [d for d in dirs if not any(pattern in d for pattern in ignore_patterns)]
14
+
15
+ for filename in filenames:
16
+ # Skip ignored files
17
+ if any(pattern in filename for pattern in ignore_patterns):
18
+ continue
19
+
20
+ file_path = os.path.join(root, filename)
21
+ files.append(file_path)
22
+
23
+ return files
24
+
25
+ def format_file_size(size_bytes: int) -> str:
26
+ """Format file size in human readable format"""
27
+ if size_bytes == 0:
28
+ return "0B"
29
+
30
+ size_names = ["B", "KB", "MB", "GB"]
31
+ i = 0
32
+ while size_bytes >= 1024 and i < len(size_names) - 1:
33
+ size_bytes /= 1024.0
34
+ i += 1
35
+
36
+ return f"{size_bytes:.1f}{size_names[i]}"
@@ -0,0 +1,278 @@
1
+ Metadata-Version: 2.4
2
+ Name: simple-vcs
3
+ Version: 1.0.0
4
+ Summary: A simple version control system written in Python
5
+ Home-page: https://github.com/yourusername/simple-vcs
6
+ Author: Your Name
7
+ Author-email: your.email@example.com
8
+ Classifier: Development Status :: 4 - Beta
9
+ Classifier: Intended Audience :: Developers
10
+ Classifier: License :: OSI Approved :: MIT License
11
+ Classifier: Operating System :: OS Independent
12
+ Classifier: Programming Language :: Python :: 3
13
+ Classifier: Programming Language :: Python :: 3.7
14
+ Classifier: Programming Language :: Python :: 3.8
15
+ Classifier: Programming Language :: Python :: 3.9
16
+ Classifier: Programming Language :: Python :: 3.10
17
+ Requires-Python: >=3.7
18
+ Description-Content-Type: text/markdown
19
+ License-File: LICENSE
20
+ Requires-Dist: click>=7.0
21
+ Dynamic: author
22
+ Dynamic: author-email
23
+ Dynamic: classifier
24
+ Dynamic: description
25
+ Dynamic: description-content-type
26
+ Dynamic: home-page
27
+ Dynamic: license-file
28
+ Dynamic: requires-dist
29
+ Dynamic: requires-python
30
+ Dynamic: summary
31
+
32
+ # README.md
33
+ # SimpleVCS
34
+
35
+ A simple version control system written in Python that provides basic VCS functionality similar to Git.
36
+
37
+ ## Features
38
+
39
+ - Initialize repositories
40
+ - Add files to staging area
41
+ - Commit changes with messages or timestamps
42
+ - View commit history with detailed information
43
+ - Show differences between commits
44
+ - Repository status tracking
45
+ - Cross-platform compatibility
46
+ - Both CLI and Python API support
47
+
48
+ ## Installation
49
+
50
+ ### From PyPI (when published)
51
+ ```bash
52
+ pip install simple-vcs
53
+ ```
54
+
55
+ ### From Source
56
+ ```bash
57
+ # Clone the repository
58
+ git clone https://github.com/muhammadsufiyanbaig/simple_vcs.git
59
+ cd simple-vcs
60
+
61
+ # Install in development mode
62
+ pip install -e .
63
+
64
+ # Or install normally
65
+ pip install .
66
+ ```
67
+
68
+ ## Quick Start
69
+
70
+ ```bash
71
+ # Initialize a new repository
72
+ svcs init
73
+
74
+ # Create a sample file
75
+ echo "Hello World" > hello.txt
76
+
77
+ # Add file to staging area
78
+ svcs add hello.txt
79
+
80
+ # Commit the changes
81
+ svcs commit -m "Add hello.txt"
82
+
83
+ # View commit history
84
+ svcs log
85
+ ```
86
+
87
+ ## Usage
88
+
89
+ ### Command Line Interface
90
+
91
+ #### Repository Management
92
+ ```bash
93
+ # Initialize a new repository in current directory
94
+ svcs init
95
+
96
+ # Initialize in specific directory
97
+ svcs init --path /path/to/project
98
+ ```
99
+
100
+ #### File Operations
101
+ ```bash
102
+ # Add single file
103
+ svcs add filename.txt
104
+
105
+ # Add multiple files
106
+ svcs add file1.txt file2.py file3.md
107
+
108
+ # Check repository status
109
+ svcs status
110
+ ```
111
+
112
+ #### Commit Operations
113
+ ```bash
114
+ # Commit with message
115
+ svcs commit -m "Your commit message"
116
+
117
+ # Commit with auto-generated timestamp
118
+ svcs commit
119
+
120
+ # View commit history
121
+ svcs log
122
+
123
+ # View limited commit history
124
+ svcs log --limit 5
125
+ ```
126
+
127
+ #### Viewing Differences
128
+ ```bash
129
+ # Show diff between last two commits
130
+ svcs diff
131
+
132
+ # Show diff between specific commits
133
+ svcs diff --c1 1 --c2 3
134
+
135
+ # Show diff between commit 2 and latest
136
+ svcs diff --c1 2
137
+ ```
138
+
139
+ ### Python API
140
+
141
+ ```python
142
+ from simple_vcs import SimpleVCS
143
+
144
+ # Create VCS instance
145
+ vcs = SimpleVCS("./my_project")
146
+
147
+ # Initialize repository
148
+ vcs.init_repo()
149
+
150
+ # Add files
151
+ vcs.add_file("example.txt")
152
+ vcs.add_file("script.py")
153
+
154
+ # Commit changes
155
+ vcs.commit("Initial commit with example files")
156
+
157
+ # Show commit history
158
+ vcs.show_log()
159
+
160
+ # Show differences between commits
161
+ vcs.show_diff(1, 2)
162
+
163
+ # Check repository status
164
+ vcs.status()
165
+ ```
166
+
167
+ ## Advanced Usage
168
+
169
+ ### Working with Multiple Files
170
+ ```python
171
+ from simple_vcs import SimpleVCS
172
+ from simple_vcs.utils import get_all_files
173
+
174
+ vcs = SimpleVCS()
175
+ vcs.init_repo()
176
+
177
+ # Add all Python files in current directory
178
+ python_files = [f for f in get_all_files(".") if f.endswith('.py')]
179
+ for file in python_files:
180
+ vcs.add_file(file)
181
+
182
+ vcs.commit("Add all Python files")
183
+ ```
184
+
185
+ ### Repository Structure
186
+ When initialized, SimpleVCS creates a `.svcs` directory containing:
187
+ ```
188
+ .svcs/
189
+ ├── objects/ # File content storage (hashed)
190
+ ├── commits.json # Commit history and metadata
191
+ ├── staging.json # Currently staged files
192
+ └── HEAD # Current commit reference
193
+ ```
194
+
195
+ ## Requirements
196
+
197
+ - Python 3.7 or higher
198
+ - click>=7.0 (for CLI functionality)
199
+
200
+ ## Development
201
+
202
+ ### Setting up Development Environment
203
+ ```bash
204
+ # Clone the repository
205
+ git clone https://github.com/yourusername/simple-vcs.git
206
+ cd simple-vcs
207
+
208
+ # Create virtual environment
209
+ python -m venv venv
210
+ source venv/bin/activate # On Windows: venv\Scripts\activate
211
+
212
+ # Install in development mode
213
+ pip install -e .
214
+
215
+ # Install development dependencies
216
+ pip install pytest pytest-cov black flake8
217
+ ```
218
+
219
+ ### Running Tests
220
+ ```bash
221
+ # Run all tests
222
+ pytest
223
+
224
+ # Run with coverage
225
+ pytest --cov=simple_vcs
226
+
227
+ # Run specific test file
228
+ pytest tests/test_core.py
229
+ ```
230
+
231
+ ## Contributing
232
+
233
+ 1. Fork the repository
234
+ 2. Create a feature branch (`git checkout -b feature/amazing-feature`)
235
+ 3. Make your changes
236
+ 4. Add tests for your changes
237
+ 5. Ensure tests pass (`pytest`)
238
+ 6. Commit your changes (`git commit -m 'Add amazing feature'`)
239
+ 7. Push to the branch (`git push origin feature/amazing-feature`)
240
+ 8. Open a Pull Request
241
+
242
+ ## Publishing to PyPI
243
+
244
+ ```bash
245
+ # Install build tools
246
+ pip install build twine
247
+
248
+ # Build the package
249
+ python -m build
250
+
251
+ # Upload to PyPI (requires PyPI account)
252
+ twine upload dist/*
253
+ ```
254
+
255
+ ## Limitations
256
+
257
+ This is a simple implementation for educational purposes. It lacks advanced features like:
258
+ - Branching and merging
259
+ - Remote repositories
260
+ - File conflict resolution
261
+ - Large file handling
262
+ - Advanced diff algorithms
263
+
264
+ ## License
265
+
266
+ This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
267
+
268
+ ## Author
269
+
270
+ Your Name - your.email@example.com
271
+
272
+ ## Changelog
273
+
274
+ ### Version 1.0.0
275
+ - Initial release
276
+ - Basic VCS functionality (init, add, commit, log, diff, status)
277
+ - CLI and Python API support
278
+ - Cross-platform compatibility
@@ -0,0 +1,10 @@
1
+ simple_vcs/__init__.py,sha256=ic-WO0wttRy6ILvZL1GdR0icHUmNNSoL6fvPjKG00tE,164
2
+ simple_vcs/cli.py,sha256=YZCzSozCNNZGwVdER121cPhpLhJ6miCiSOiqYcfz664,1314
3
+ simple_vcs/core.py,sha256=q4FF7s6y0PRU7cMfq9E32wMsR-jrHBo_8m5qj5heRnM,9771
4
+ simple_vcs/utils.py,sha256=CTd4gDdHqP-dawjtEeKU3csnT-Fe7_SN9a5ENQlo7wk,1202
5
+ simple_vcs-1.0.0.dist-info/licenses/LICENSE,sha256=6o_m1QgCywYf-QZnE6cuLTwu5kVVQn3vJ7JJUd0V_iY,1085
6
+ simple_vcs-1.0.0.dist-info/METADATA,sha256=5tmnxoOajcwq4kXaAbunr1nGrXfjoPRn5V_sZnCN8Ws,5908
7
+ simple_vcs-1.0.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
8
+ simple_vcs-1.0.0.dist-info/entry_points.txt,sha256=19JeWUvRFzwKF5p_iLQiSwCV3XTgxB7mkTLmFGrc_aY,45
9
+ simple_vcs-1.0.0.dist-info/top_level.txt,sha256=YcaiuqQjjXFL-H62tfC-hTcg-7sWFmLh65zghskauL4,11
10
+ simple_vcs-1.0.0.dist-info/RECORD,,
@@ -0,0 +1,5 @@
1
+ Wheel-Version: 1.0
2
+ Generator: setuptools (80.9.0)
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
5
+
@@ -0,0 +1,2 @@
1
+ [console_scripts]
2
+ svcs = simple_vcs.cli:main
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2024 SimpleVCS
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1 @@
1
+ simple_vcs