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'),
34 #####################################################
35 # Used by the create branch dialog
37 'local_branches': cmds
.git_branch(remote
=False),
38 'remote_branches': cmds
.git_branch(remote
=True),
39 'tags': cmds
.git_tag(),
41 #####################################################
42 # Used by the repo browser
45 # These are parallel lists
50 # All items below here are re-calculated in
53 'directory_entries': {},
55 # These are also parallel lists
62 def all_branches(self
):
63 return (self
.get_local_branches()
64 + self
.get_remote_branches())
66 def init_branch_data(self
):
67 remotes
= cmds
.git_remote()
68 remote_branches
= cmds
.git_branch(remote
=True)
69 local_branches
= cmds
.git_branch(remote
=False)
73 self
.set_local_branch('')
74 self
.set_remote_branch('')
75 self
.set_remotes(remotes
)
76 self
.set_remote_branches(remote_branches
)
77 self
.set_local_branches(local_branches
)
80 def init_browser_data(self
):
81 '''This scans over self.(names, sha1s, types) to generate
82 directories, directory_entries, and subtree_*'''
84 # Collect data for the model
85 if not self
.get_branch(): return
87 self
.subtree_types
= []
88 self
.subtree_sha1s
= []
89 self
.subtree_names
= []
91 self
.directory_entries
= {}
93 # Lookup the tree info
94 tree_info
= cmds
.git_ls_tree(self
.get_branch())
96 self
.set_types(map( lambda(x
): x
[1], tree_info
))
97 self
.set_sha1s(map( lambda(x
): x
[2], tree_info
))
98 self
.set_names(map( lambda(x
): x
[3], tree_info
))
100 if self
.directory
: self
.directories
.append('..')
102 dir_entries
= self
.directory_entries
103 dir_regex
= re
.compile('([^/]+)/')
107 for idx
, name
in enumerate(self
.names
):
109 if not name
.startswith(self
.directory
): continue
110 name
= name
[ len(self
.directory
): ]
113 # This is a directory...
114 match
= dir_regex
.match(name
)
115 if not match
: continue
117 dirent
= match
.group(1) + '/'
118 if dirent
not in self
.directory_entries
:
119 self
.directory_entries
[dirent
] = []
121 if dirent
not in dirs_seen
:
122 dirs_seen
[dirent
] = True
123 self
.directories
.append(dirent
)
125 entry
= name
.replace(dirent
, '')
126 entry_match
= dir_regex
.match(entry
)
128 subdir
= entry_match
.group(1) + '/'
129 if subdir
in subdirs_seen
: continue
130 subdirs_seen
[subdir
] = True
131 dir_entries
[dirent
].append(subdir
)
133 dir_entries
[dirent
].append(entry
)
135 self
.subtree_types
.append(self
.types
[idx
])
136 self
.subtree_sha1s
.append(self
.sha1s
[idx
])
137 self
.subtree_names
.append(name
)
139 def get_tree_node(self
, idx
):
140 return (self
.get_types()[idx
],
141 self
.get_sha1s()[idx
],
142 self
.get_names()[idx
] )
144 def get_subtree_node(self
, idx
):
145 return (self
.get_subtree_types()[idx
],
146 self
.get_subtree_sha1s()[idx
],
147 self
.get_subtree_names()[idx
] )
149 def add_signoff(self
,*rest
):
150 '''Adds a standard Signed-off by: tag to the end
151 of the current commit message.'''
153 msg
= self
.get_commitmsg()
154 signoff
=('Signed-off by: %s <%s>'
155 %(self
.get_name(), self
.get_email()))
157 if signoff
not in msg
:
158 self
.set_commitmsg(msg
+ '\n\n' + signoff
)
160 def apply_diff(self
, filename
):
161 return cmds
.git_apply(filename
)
163 def get_uncommitted_item(self
, row
):
164 return(self
.get_unstaged() + self
.get_untracked())[row
]
166 def __get_squash_msg_path(self
):
167 return os
.path
.join(os
.getcwd(), '.git', 'SQUASH_MSG')
169 def has_squash_msg(self
):
170 squash_msg
= self
.__get
_squash
_msg
_path
()
171 return os
.path
.exists(squash_msg
)
173 def get_squash_msg(self
):
174 return utils
.slurp(self
.__get
_squash
_msg
_path
())
176 def get_prev_commitmsg(self
,*rest
):
177 '''Queries git for the latest commit message and sets it in
180 commit_lines
= cmds
.git_show('HEAD').split('\n')
181 for idx
, msg
in enumerate(commit_lines
):
184 if msg
.startswith('diff --git'):
187 commit_msg
.append(msg
)
188 self
.set_commitmsg('\n'.join(commit_msg
).rstrip())
190 def update_status(self
):
191 # This allows us to defer notification until the
192 # we finish processing data
193 notify_enabled
= self
.get_notify()
194 self
.set_notify(False)
196 # Reset the staged and unstaged model lists
197 # NOTE: the model's unstaged list is used to
198 # hold both unstaged and untracked files.
203 # Read git status items
206 untracked_items
) = cmds
.git_status()
208 # Gather items to be committed
209 for staged
in staged_items
:
210 if staged
not in self
.get_staged():
211 self
.add_staged(staged
)
213 # Gather unindexed items
214 for unstaged
in unstaged_items
:
215 if unstaged
not in self
.get_unstaged():
216 self
.add_unstaged(unstaged
)
218 # Gather untracked items
219 for untracked
in untracked_items
:
220 if untracked
not in self
.get_untracked():
221 self
.add_untracked(untracked
)
223 # Re-enable notifications and emit changes
224 self
.set_notify(notify_enabled
)
225 self
.notify_observers('staged', 'unstaged')