6 from model
import Model
11 # chdir to the root of the git tree. This is critical
12 # to being able to properly use the git porcelain.
13 cdup
= cmds
.git_show_cdup()
14 if cdup
: os
.chdir(cdup
)
16 Model
.__init
__(self
, {
17 #####################################################
18 # Used in various places
19 'remotes': cmds
.git_remote(),
24 #####################################################
25 # Used primarily by the main UI
26 'project': os
.path
.basename(os
.getcwd()),
27 'name': cmds
.git_config('user.name'),
28 'email': cmds
.git_config('user.email'),
33 'all_unstaged': [], # unstaged+untracked
35 #####################################################
36 # Used by the create branch dialog
38 'local_branches': cmds
.git_branch(remote
=False),
39 'remote_branches': cmds
.git_branch(remote
=True),
40 'tags': cmds
.git_tag(),
42 #####################################################
43 # Used by the repo browser
46 # These are parallel lists
51 # All items below here are re-calculated in
54 'directory_entries': {},
56 # These are also parallel lists
63 def all_branches(self
):
64 return (self
.get_local_branches()
65 + self
.get_remote_branches())
67 def init_branch_data(self
):
68 remotes
= cmds
.git_remote()
69 remote_branches
= cmds
.git_branch(remote
=True)
70 local_branches
= cmds
.git_branch(remote
=False)
73 self
.set_remotes(remotes
)
74 self
.set_remote_branches(remote_branches
)
75 self
.set_local_branches(local_branches
)
78 self
.set_local_branch('')
79 self
.set_remote_branch('')
81 def set_remote(self
,remote
):
83 self
.set('remote',remote
)
84 branches
= utils
.grep('%s/\S+$' % remote
,
85 cmds
.git_branch(remote
=True))
86 self
.set_remote_branches(branches
)
88 def init_browser_data(self
):
89 '''This scans over self.(names, sha1s, types) to generate
90 directories, directory_entries, and subtree_*'''
92 # Collect data for the model
93 if not self
.get_branch(): return
95 self
.subtree_types
= []
96 self
.subtree_sha1s
= []
97 self
.subtree_names
= []
99 self
.directory_entries
= {}
101 # Lookup the tree info
102 tree_info
= cmds
.git_ls_tree(self
.get_branch())
104 self
.set_types(map( lambda(x
): x
[1], tree_info
))
105 self
.set_sha1s(map( lambda(x
): x
[2], tree_info
))
106 self
.set_names(map( lambda(x
): x
[3], tree_info
))
108 if self
.directory
: self
.directories
.append('..')
110 dir_entries
= self
.directory_entries
111 dir_regex
= re
.compile('([^/]+)/')
115 for idx
, name
in enumerate(self
.names
):
117 if not name
.startswith(self
.directory
): continue
118 name
= name
[ len(self
.directory
): ]
121 # This is a directory...
122 match
= dir_regex
.match(name
)
123 if not match
: continue
125 dirent
= match
.group(1) + '/'
126 if dirent
not in self
.directory_entries
:
127 self
.directory_entries
[dirent
] = []
129 if dirent
not in dirs_seen
:
130 dirs_seen
[dirent
] = True
131 self
.directories
.append(dirent
)
133 entry
= name
.replace(dirent
, '')
134 entry_match
= dir_regex
.match(entry
)
136 subdir
= entry_match
.group(1) + '/'
137 if subdir
in subdirs_seen
: continue
138 subdirs_seen
[subdir
] = True
139 dir_entries
[dirent
].append(subdir
)
141 dir_entries
[dirent
].append(entry
)
143 self
.subtree_types
.append(self
.types
[idx
])
144 self
.subtree_sha1s
.append(self
.sha1s
[idx
])
145 self
.subtree_names
.append(name
)
147 def get_tree_node(self
, idx
):
148 return (self
.get_types()[idx
],
149 self
.get_sha1s()[idx
],
150 self
.get_names()[idx
] )
152 def get_subtree_node(self
, idx
):
153 return (self
.get_subtree_types()[idx
],
154 self
.get_subtree_sha1s()[idx
],
155 self
.get_subtree_names()[idx
] )
157 def add_signoff(self
,*rest
):
158 '''Adds a standard Signed-off by: tag to the end
159 of the current commit message.'''
161 msg
= self
.get_commitmsg()
162 signoff
=('Signed-off by: %s <%s>'
163 %(self
.get_name(), self
.get_email()))
165 if signoff
not in msg
:
166 self
.set_commitmsg(msg
+ '\n\n' + signoff
)
168 def apply_diff(self
, filename
):
169 return cmds
.git_apply(filename
)
171 def get_uncommitted_item(self
, row
):
172 return(self
.get_unstaged() + self
.get_untracked())[row
]
174 def __get_squash_msg_path(self
):
175 return os
.path
.join(os
.getcwd(), '.git', 'SQUASH_MSG')
177 def has_squash_msg(self
):
178 squash_msg
= self
.__get
_squash
_msg
_path
()
179 return os
.path
.exists(squash_msg
)
181 def get_squash_msg(self
):
182 return utils
.slurp(self
.__get
_squash
_msg
_path
())
184 def get_prev_commitmsg(self
,*rest
):
185 '''Queries git for the latest commit message and sets it in
188 commit_lines
= cmds
.git_show('HEAD').split('\n')
189 for idx
, msg
in enumerate(commit_lines
):
192 if msg
.startswith('diff --git'):
195 commit_msg
.append(msg
)
196 self
.set_commitmsg('\n'.join(commit_msg
).rstrip())
198 def update_status(self
):
199 # This allows us to defer notification until the
200 # we finish processing data
201 notify_enabled
= self
.get_notify()
202 self
.set_notify(False)
204 # Reset the staged and unstaged model lists
205 # NOTE: the model's unstaged list is used to
206 # hold both unstaged and untracked files.
211 # Read git status items
214 untracked_items
) = cmds
.git_status()
216 # Gather items to be committed
217 for staged
in staged_items
:
218 if staged
not in self
.get_staged():
219 self
.add_staged(staged
)
221 # Gather unindexed items
222 for unstaged
in unstaged_items
:
223 if unstaged
not in self
.get_unstaged():
224 self
.add_unstaged(unstaged
)
226 # Gather untracked items
227 for untracked
in untracked_items
:
228 if untracked
not in self
.get_untracked():
229 self
.add_untracked(untracked
)
231 # Provide a convenient representation of the unstaged list
232 self
.set_all_unstaged(self
.get_unstaged() + self
.get_untracked())
234 # Re-enable notifications and emit changes
235 self
.set_notify(notify_enabled
)
236 self
.notify_observers('all_unstaged', 'staged')