Skip to content

Commit bd54646

Browse files
committed
Fixed issue where untracked files are not cleaned during update by introducing a --clean-files #215
To ensure that this is not used by accident the full command is `mbed update --clean --clean-files` Also rename --force switch to --clean-deps for consistency, e..g `mbed update --clean --clean-deps`
1 parent 45b425c commit bd54646

File tree

2 files changed

+37
-28
lines changed

2 files changed

+37
-28
lines changed

README.md

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -295,19 +295,21 @@ Run `mbed update <tag_name|revision> --clean`
295295

296296
__When you have unpublished local libraries__
297297

298-
There are two additional options that define how unpublished local libraries are handled:
298+
There are 3 additional options that define how unpublished local libraries are handled:
299299

300-
`mbed update --ignore` - update the current program or library and its dependencies, and ignore any local unpublished libraries (they won't be deleted or modified, just ignored).
300+
`mbed update --clean-deps` - update the current program or library and its dependencies, and discard all local unpublished repositories. Use this with caution as your local unpublished repositories cannot be restored unless you have a backup copy.
301+
302+
`mbed update --clean-files` - update the current program or library and its dependencies, discard local uncommitted changes and remove any untracked or ignored files. Use this with caution as your local unpublished repositories cannot be restored unless you have a backup copy.
301303

302-
`mbed update --force` - update the current program or library and its dependencies, and discard all local unpublished repositories. Use this with caution as your local unpublished repositories cannot be restored unless you have a backup copy.
304+
`mbed update --ignore` - update the current program or library and its dependencies, and ignore any local unpublished libraries (they won't be deleted or modified, just ignored).
303305

304306
__Combining update options__
305307

306308
You can combine the options above for the following scenarios:
307309

308-
`mbed update --clean --ignore` - update the current program or library and its dependencies, but ignore any local repositories. mbed-cli will update whatever it can from public repositories.
310+
`mbed update --clean --clean-deps --clean-files` - update the current program or library and its dependencies, remove all local unpublished libraries, discard local uncommitted changes, and remove all untracked or ignored files. This wipes every single change that you made in the source tree and restores the stock layout.
309311

310-
`mbed update --clean --force` - update the current program or library and all its dependencies, and restore my source tree to stock layout. This wipes every change that you made in the source tree that didn't belong to the original commit, including uncommitted changes and unpublished local libraries.
312+
`mbed update --clean --ignore` - update the current program or library and its dependencies, but ignore any local repositories. mbed CLI will update whatever it can from the public repositories.
311313

312314
Use these with caution as your uncommitted changes and unpublished libraries cannot be restored.
313315

mbed/mbed.py

Lines changed: 30 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -317,7 +317,7 @@ def checkout(rev, clean=False):
317317
error(e[1], e[0])
318318
Bld.seturl(url+'/'+rev)
319319

320-
def update(rev=None, clean=False, is_local=False):
320+
def update(rev=None, clean=False, clean_files=False, is_local=False):
321321
return Bld.checkout(rev, clean)
322322

323323
def untracked():
@@ -398,14 +398,19 @@ def discard():
398398
log("Discarding local changes in \"%s\"" % os.path.basename(os.getcwd()))
399399
popen([hg_cmd, 'update', '-C'] + (['-v'] if very_verbose else ([] if verbose else ['-q'])))
400400

401-
def checkout(rev, clean=False):
401+
def checkout(rev, clean=False, clean_files=False):
402402
log("Checkout \"%s\" in %s to %s" % (rev, os.path.basename(os.getcwd()), rev))
403+
if clean_files:
404+
files = pquery([hg_cmd, 'status', '--no-status', '-ui']).splitlines()
405+
for f in files:
406+
log("Remove untracked file \"%s\"" % f)
407+
os.remove(f)
403408
popen([hg_cmd, 'update'] + (['-C'] if clean else []) + (['-r', rev] if rev else []) + (['-v'] if very_verbose else ([] if verbose else ['-q'])))
404409

405-
def update(rev=None, clean=False, is_local=False):
410+
def update(rev=None, clean=False, clean_files=False, is_local=False):
406411
if not is_local:
407412
Hg.fetch()
408-
Hg.checkout(rev, clean)
413+
Hg.checkout(rev, clean, clean_files)
409414

410415
def status():
411416
return pquery([hg_cmd, 'status'] + (['-v'] if very_verbose else ([] if verbose else ['-q'])))
@@ -414,8 +419,7 @@ def dirty():
414419
return pquery([hg_cmd, 'status', '-q'])
415420

416421
def untracked():
417-
result = pquery([hg_cmd, 'status', '-u'])
418-
return re.sub(r'^\? ', '', result).splitlines()
422+
return pquery([hg_cmd, 'status', '--no-status', '-u']).splitlines()
419423

420424
def outgoing():
421425
try:
@@ -571,11 +575,11 @@ def fetch():
571575
log("Fetching revisions from remote repository to \"%s\"" % os.path.basename(os.getcwd()))
572576
popen([git_cmd, 'fetch', '--all'] + (['-v'] if very_verbose else ([] if verbose else ['-q'])))
573577

574-
def discard():
578+
def discard(clean_files=False):
575579
log("Discarding local changes in \"%s\"" % os.path.basename(os.getcwd()))
576580
pquery([git_cmd, 'reset', 'HEAD'] + ([] if very_verbose else ['-q'])) # unmarks files for commit
577581
pquery([git_cmd, 'checkout', '.'] + ([] if very_verbose else ['-q'])) # undo modified files
578-
pquery([git_cmd, 'clean', '-fdq'] + ([] if very_verbose else ['-q'])) # cleans up untracked files and folders
582+
pquery([git_cmd, 'clean', '-fd'] + (['-x'] if clean_files else []) + (['-q'] if very_verbose else ['-q'])) # cleans up untracked files and folders
579583

580584
def merge(dest):
581585
log("Merging \"%s\" with \"%s\"" % (os.path.basename(os.getcwd()), dest))
@@ -594,9 +598,9 @@ def checkout(rev, clean=False):
594598
popen([git_cmd, 'checkout', branch] + ([] if very_verbose else ['-q']))
595599
break
596600

597-
def update(rev=None, clean=False, is_local=False):
601+
def update(rev=None, clean=False, clean_files=False, is_local=False):
598602
if clean:
599-
Git.discard()
603+
Git.discard(clean_files)
600604
if not is_local:
601605
Git.fetch()
602606
if rev:
@@ -1050,21 +1054,21 @@ def set_cache(self, url):
10501054
warning("Unable to cache \"%s\" to \"%s\"" % (self.path, cpath))
10511055
return False
10521056

1053-
def can_update(self, clean, force):
1057+
def can_update(self, clean, clean_deps):
10541058
err = None
1055-
if (self.is_local or self.url is None) and not force:
1059+
if (self.is_local or self.url is None) and not clean_deps:
10561060
err = (
10571061
"Preserving local library \"%s\" in \"%s\".\nPlease publish this library to a remote URL to be able to restore it at any time."
10581062
"You can use --ignore switch to ignore all local libraries and update only the published ones.\n"
1059-
"You can also use --force switch to remove all local libraries. WARNING: This action cannot be undone." % (self.name, self.path))
1063+
"You can also use --clean-deps switch to remove all local libraries. WARNING: This action cannot be undone." % (self.name, self.path))
10601064
elif not clean and self.dirty():
10611065
err = (
10621066
"Uncommitted changes in \"%s\" in \"%s\".\nPlease discard or stash them first and then retry update.\n"
10631067
"You can also use --clean switch to discard all uncommitted changes. WARNING: This action cannot be undone." % (self.name, self.path))
1064-
elif not force and self.outgoing():
1068+
elif not clean_deps and self.outgoing():
10651069
err = (
10661070
"Unpublished changes in \"%s\" in \"%s\".\nPlease publish them first using the \"publish\" command.\n"
1067-
"You can also use --force to discard all local commits and replace the library with the one included in this revision. WARNING: This action cannot be undone." % (self.name, self.path))
1071+
"You can also use --clean-deps to discard all local commits and replace the library with the one included in this revision. WARNING: This action cannot be undone." % (self.name, self.path))
10681072

10691073
return (False, err) if err else (True, "OK")
10701074

@@ -1670,8 +1674,9 @@ def publish(all=None, top=True):
16701674
# Update command
16711675
@subcommand('update',
16721676
dict(name='rev', nargs='?', help='Revision, tag or branch'),
1673-
dict(name=['-C', '--clean'], action='store_true', help='Perform a clean update and discard all local changes. WARNING: This action cannot be undone. Use with caution.'),
1674-
dict(name=['-F', '--force'], action='store_true', help='Enforce the original layout and will remove any local libraries and also libraries containing uncommitted or unpublished changes. WARNING: This action cannot be undone. Use with caution.'),
1677+
dict(name=['-C', '--clean'], action='store_true', help='Perform a clean update and discard all modified or untracked files. WARNING: This action cannot be undone. Use with caution.'),
1678+
dict(name='--clean-files', action='store_true', help='Remove any local ignored files. Requires \'--clean\'. WARNING: This will wipe all local uncommitted, untracked and ignored files. Use with extreme caution.'),
1679+
dict(name='--clean-deps', action='store_true', help='Remove any local libraries and also libraries containing uncommitted or unpublished changes. Requires \'--clean\'. WARNING: This action cannot be undone. Use with caution.'),
16751680
dict(name=['-I', '--ignore'], action='store_true', help='Ignore errors related to unpublished libraries, unpublished or uncommitted changes, and attempt to update from associated remote repository URLs.'),
16761681
dict(name='--depth', nargs='?', help='Number of revisions to fetch from the remote repository. Default: all revisions.'),
16771682
dict(name='--protocol', nargs='?', help='Transport protocol for the source control management. Supported: https, http, ssh, git. Default: inferred from URL.'),
@@ -1680,7 +1685,7 @@ def publish(all=None, top=True):
16801685
"Updates this %s and its dependencies to specified branch, tag or revision.\n"
16811686
"Alternatively fetches from associated remote repository URL and updates to the\n"
16821687
"latest revision in the current branch." % cwd_type))
1683-
def update(rev=None, clean=False, force=False, ignore=False, top=True, depth=None, protocol=None):
1688+
def update(rev=None, clean=False, clean_files=False, clean_deps=False, ignore=False, top=True, depth=None, protocol=None):
16841689
if top and clean:
16851690
sync()
16861691

@@ -1705,7 +1710,7 @@ def update(rev=None, clean=False, force=False, ignore=False, top=True, depth=Non
17051710
repo.revtype(rev, True)))
17061711

17071712
try:
1708-
repo.update(rev, clean, repo.is_local)
1713+
repo.update(rev, clean, clean_files, repo.is_local)
17091714
except ProcessException as e:
17101715
err = "Unable to update \"%s\" to %s" % (repo.name, repo.revtype(rev, True))
17111716
if depth:
@@ -1726,7 +1731,7 @@ def update(rev=None, clean=False, force=False, ignore=False, top=True, depth=Non
17261731
gc = False
17271732
with cd(lib.path):
17281733
lib_repo = Repo.fromrepo(lib.path)
1729-
gc, msg = lib_repo.can_update(clean, force)
1734+
gc, msg = lib_repo.can_update(clean, clean_deps)
17301735
if gc:
17311736
action("Removing library \"%s\" (obsolete)" % (relpath(cwd_root, lib.path)))
17321737
rmtree_readonly(lib.path)
@@ -1747,7 +1752,7 @@ def update(rev=None, clean=False, force=False, ignore=False, top=True, depth=Non
17471752
if lib.url != lib_repo.url: # Repository URL has changed
17481753
gc = False
17491754
with cd(lib.path):
1750-
gc, msg = lib_repo.can_update(clean, force)
1755+
gc, msg = lib_repo.can_update(clean, clean_deps)
17511756
if gc:
17521757
action("Removing library \"%s\" (changed URL). Will add from new URL." % (relpath(cwd_root, lib.path)))
17531758
rmtree_readonly(lib.path)
@@ -1765,10 +1770,12 @@ def update(rev=None, clean=False, force=False, ignore=False, top=True, depth=Non
17651770
repo.ignore(relpath(repo.path, lib.path))
17661771
else:
17671772
with cd(lib.path):
1768-
update(lib.rev, clean, force, ignore=ignore, top=False)
1773+
update(lib.rev, clean=clean, clean_files=clean_files, clean_deps=clean_deps, ignore=ignore, top=False)
17691774

17701775
if top:
1771-
Program(repo.path).post_action()
1776+
program = Program(repo.path)
1777+
program.set_root()
1778+
program.post_action()
17721779

17731780

17741781
# Synch command

0 commit comments

Comments
 (0)