-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathgit_bot.py
More file actions
125 lines (98 loc) · 3.82 KB
/
git_bot.py
File metadata and controls
125 lines (98 loc) · 3.82 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
"""
Git operations for creating backdated commits
"""
import os
import json
from datetime import datetime, timedelta
from git import Repo, Actor
def calculate_date(weeks, days):
"""Calculate date based on weeks and days offset from one year ago"""
one_year_ago = datetime.now() - timedelta(days=365)
target_date = one_year_ago + timedelta(weeks=weeks, days=days+1)
return target_date
def initialize_repo(repo_url, target_dir):
"""
Initialize or clone a repository
"""
# Create directory if it doesn't exist
if not os.path.exists(target_dir):
os.makedirs(target_dir, exist_ok=True)
# Check if it's already a repo
git_dir = os.path.join(target_dir, '.git')
if os.path.exists(git_dir):
repo = Repo(target_dir)
# Update remote
if 'origin' in [remote.name for remote in repo.remotes]:
repo.delete_remote('origin')
repo.create_remote('origin', repo_url)
else:
# Initialize new repo
repo = Repo.init(target_dir)
repo.create_remote('origin', repo_url)
# Create initial data file
data_file = os.path.join(target_dir, 'data.json')
with open(data_file, 'w') as f:
json.dump({}, f)
return repo
def mark_commit(repo, week, day, intensity=1, message=None, author_name=None, author_email=None):
"""
Create a commit (or multiple for intensity) at a specific coordinate
"""
target_date = calculate_date(week, day)
data_file = os.path.join(repo.working_dir, 'data.json')
# Write data
data = {
'date': target_date.isoformat(),
'week': week,
'day': day
}
with open(data_file, 'w') as f:
json.dump(data, f, indent=2)
# Stage the file
repo.index.add(['data.json'])
# Create commits (intensity times)
for i in range(intensity):
commit_message = message or f"{target_date.isoformat()} ({week},{day})"
# Set author if provided
if author_name and author_email:
author = Actor(author_name, author_email)
repo.index.commit(commit_message, author=author, committer=author, author_date=target_date, commit_date=target_date)
else:
# Use git config default
repo.index.commit(commit_message, author_date=target_date, commit_date=target_date)
def create_pattern_commits(repo, coordinates, intensity=1, progress_callback=None, author_name=None, author_email=None):
"""
Create commits from pattern coordinates
"""
total = len(coordinates)
for i, coord in enumerate(coordinates):
week = coord['week']
day = coord['day']
char = coord['char']
message = f"Pattern: {char} ({week},{day})"
mark_commit(repo, week, day, intensity, message, author_name, author_email)
if progress_callback:
progress_callback({
'current': i + 1,
'total': total,
'week': week,
'day': day,
'char': char,
'percentage': round(((i + 1) / total) * 100)
})
# Push to remote
try:
origin = repo.remote('origin')
# Get current branch or default to 'main'
if repo.head.is_detached or not repo.heads:
# Create main branch if it doesn't exist
if 'main' not in [h.name for h in repo.heads]:
repo.create_head('main')
repo.heads.main.checkout()
current_branch = 'main'
else:
current_branch = repo.active_branch.name
# Push with force to handle first push
origin.push(refspec=f'{current_branch}:{current_branch}', force=True)
except Exception as e:
raise Exception(f"Failed to push to remote: {str(e)}")