def _parse_git_diff(dspath, diff_thingie=None, paths=None, ignore_submodules='none', staged=False): # use '--work-tree=.' to get direct omde to cooperate cmd = ['git', '--work-tree=.', 'diff', '--raw', # file names NULL terminated '-z', # how to treat submodules (see git diff docs) '--ignore-submodules={}'.format(ignore_submodules), # never abbreviate sha sums '--abbrev=40'] if staged: cmd.append('--staged') if diff_thingie: cmd.append(diff_thingie) if paths: cmd.append('--') cmd.extend(ap['path'] for ap in paths if ap.get('raw_input', False)) try: stdout = GitWitlessRunner(cwd=dspath).run( cmd, protocol=StdOutErrCapture)['stdout'] except CommandError as e: if 'bad revision' in e.stderr: yield dict( path=dspath, type='dataset', status='impossible', message=e.stderr.strip()) return raise ap = None for line in stdout.split('\0'): if not line: continue if line.startswith(':'): # a new path # yield any existing one if ap: yield ap ap = None # start new record m_src, m_dst, sha_src, sha_dst, status = \ line[1:].split() ap = dict( mode_src=int(m_src, base=8), mode=int(m_dst, base=8), revision_src=sha_src if sha_src != '0' * 40 else None, revision=sha_dst if sha_dst != '0' * 40 else None, parentds=dspath) _translate_status(status, ap) _translate_type(ap['mode'], ap, 'type') _translate_type(ap['mode_src'], ap, 'type_src') else: # a filename if 'path' in ap: ap['path_src'] = ap['path'] ap['path'] = opj(dspath, line) if ap: yield ap
def _get_untracked_content(dspath, report_untracked, paths=None): cmd = [ 'git', '--work-tree=.', 'status', '--porcelain', # file names NULL terminated '-z', # we never want to touch submodules, they cannot be untracked '--ignore-submodules=all', # fully untracked dirs as such, the rest as files '--untracked={}'.format(report_untracked) ] try: stdout = GitWitlessRunner(cwd=dspath).run( cmd, protocol=StdOutErrCapture)['stdout'] except CommandError as e: # TODO should we catch any and handle them in here? raise e if paths: paths = [r['path'] for r in paths] if len(paths) == 1 and paths[0] == dspath: # nothing to filter paths = None from datalad.utils import ensure_unicode for line in stdout.split('\0'): if not line: continue line = ensure_unicode(line) if not line.startswith('?? '): # nothing untracked, ignore, task of `diff` continue apath = opj( dspath, # strip state marker line[3:]) norm_apath = normpath(apath) if paths and not any(norm_apath == p or path_startswith(apath, p) for p in paths): # we got a whitelist for paths, don't report any other continue ap = dict(path=norm_apath, parentds=dspath, state='untracked', type='directory' if isdir(apath) else 'file') yield ap