def test_stamp_is_current_working_set(first_stamp): """Check we are stamping the current working set """ with NewCountedDirectory('build3') as d2: banner('TESTING STAMP CURRENT WORKING SET') muddle(['unstamp', first_stamp]) # So, we've selected specific revisions for all of our checkouts # and thus they are all in "detached HEAD" state revisions = capture_revisions() # XXX To be considered XXX # Here, we are deliberately making a change that we do not push to the # remote repository. Thus our stamp file will contain a revision id # that no-one else can make sense of. This may be a Bad Thing. # Indeed, if we try to do this with a bzr repository, our own code # in 'muddle query checkout-id' would use 'bzr missing' and notice that # the revision was not present at the far end, and give up with a # complaint at that point. with Directory('src'): with Directory('first_co'): append('Makefile.muddle', '\n# A comment\n') git('commit Makefile.muddle -m "Add a comment"') # Don't forget that ".strip()" to remove the trailing newline! first_co_rev2 = captured_muddle(['query', 'checkout-id', 'first_co']).strip() if first_co_rev2 == revisions['first_co']: raise GiveUp('The revision of first_co did not change') revisions['first_co'] = first_co_rev2 muddle(['stamp', 'save', 'amended.stamp']) stamp = VersionStamp.from_file('amended.stamp') if len(stamp.checkouts) != len(revisions): raise GiveUp('Stamp file has %d checkouts, build tree %d' % (len(stamp.checkouts), len(revisions))) for co in stamp.checkouts: if co.domain: dom_plus_name = '(%s)%s' % (co.domain, co.name) else: dom_plus_name = co.name repo = stamp.checkouts[co][ -1] # ah, named tuples would be good here #print dom_plus_name #print ' S:',repo.revision #print ' D:',revisions[dom_plus_name] if repo.revision != revisions[dom_plus_name]: raise GiveUp( 'Checkout %s is revision %s in stamp file,' ' %s on disk' % (dom_plus_name, repo.revision, revisions[dom_plus_name]))
def test_options(): """Test we can read back options from a stamp file. """ fname = 'test_options.stamp' touch(fname, OPTIONS_TEST) v = VersionStamp.from_file(fname) if len(v.problems) != 4: raise GiveUp('Expected 4 problems reading %s, got %d' % (fname, len(v.problems))) # Make the problem order deterministic v.problems.sort() check_problem( v.problems[0], "Cannot convert value to integer, for 'option~BadFred = int:ThreadNeedle'" ) check_problem( v.problems[1], "No datatype (no colon in value), for 'option~Aha~There = No colons here'" ) check_problem( v.problems[2], "Unrecognised datatype 'what' (not bool, int or str), for 'option~AhaTwo = what:pardon'" ) check_problem( v.problems[3], "Value is not True or False, for 'option~BadJim = bool:Immensity'") co_label = Label(LabelType.Checkout, 'co_name', None, LabelTag.CheckedOut) co_dir, co_leaf, repo = v.checkouts[co_label] options = v.options[co_label] expected_repo = 'file:///Users/tibs/sw/m3/tests/transient/repo/second_co' if co_dir is not None or co_leaf != 'co_name' or \ str(repo) != expected_repo: raise GiveUp('Error in reading checkout back\n' ' co_dir %s, expected None\n' ' co_leaf %s, expected co_name\n' ' repo %s\n' ' expected %s' % (co_dir, co_leaf, repo, expected_repo)) if len(options) != 3 or \ options['Jim'] != False or \ options['Bill'] != 'Some sort of string' or \ options['Fred'] != 99: raise GiveUp( 'Error in reading checkout options back\n' " expected {'Jim': False, 'Bill': 'Some sort of string', 'Fred': 99}\n" ' got %s' % options)
def test_stamp_is_current_working_set(first_stamp): """Check we are stamping the current working set """ with NewCountedDirectory('build3') as d2: banner('TESTING STAMP CURRENT WORKING SET') muddle(['unstamp', first_stamp]) # So, we've selected specific revisions for all of our checkouts # and thus they are all in "detached HEAD" state revisions = capture_revisions() # XXX To be considered XXX # Here, we are deliberately making a change that we do not push to the # remote repository. Thus our stamp file will contain a revision id # that no-one else can make sense of. This may be a Bad Thing. # Indeed, if we try to do this with a bzr repository, our own code # in 'muddle query checkout-id' would use 'bzr missing' and notice that # the revision was not present at the far end, and give up with a # complaint at that point. with Directory('src'): with Directory('first_co'): append('Makefile.muddle', '\n# A comment\n') git('commit Makefile.muddle -m "Add a comment"') # Don't forget that ".strip()" to remove the trailing newline! first_co_rev2 = captured_muddle(['query', 'checkout-id', 'first_co']).strip() if first_co_rev2 == revisions['first_co']: raise GiveUp('The revision of first_co did not change') revisions['first_co'] = first_co_rev2 muddle(['stamp', 'save', 'amended.stamp']) stamp = VersionStamp.from_file('amended.stamp') if len(stamp.checkouts) != len(revisions): raise GiveUp('Stamp file has %d checkouts, build tree %d'%(len(stamp.checkouts), len(revisions))) for co in stamp.checkouts: if co.domain: dom_plus_name = '(%s)%s'%(co.domain, co.name) else: dom_plus_name = co.name repo = stamp.checkouts[co][-1] # ah, named tuples would be good here #print dom_plus_name #print ' S:',repo.revision #print ' D:',revisions[dom_plus_name] if repo.revision != revisions[dom_plus_name]: raise GiveUp('Checkout %s is revision %s in stamp file,' ' %s on disk'%(dom_plus_name, repo.revision, revisions[dom_plus_name]))
def test_options(): """Test we can read back options from a stamp file. """ fname = 'test_options.stamp' touch(fname, OPTIONS_TEST) v = VersionStamp.from_file(fname) if len(v.problems) != 4: raise GiveUp('Expected 4 problems reading %s, got %d'%(fname, len(v.problems))) # Make the problem order deterministic v.problems.sort() check_problem(v.problems[0], "Cannot convert value to integer, for 'option~BadFred = int:ThreadNeedle'") check_problem(v.problems[1], "No datatype (no colon in value), for 'option~Aha~There = No colons here'") check_problem(v.problems[2], "Unrecognised datatype 'what' (not bool, int or str), for 'option~AhaTwo = what:pardon'") check_problem(v.problems[3], "Value is not True or False, for 'option~BadJim = bool:Immensity'") co_label = Label(LabelType.Checkout, 'co_name', None, LabelTag.CheckedOut) co_dir, co_leaf, repo = v.checkouts[co_label] options = v.options[co_label] expected_repo = 'file:///Users/tibs/sw/m3/tests/transient/repo/second_co' if co_dir is not None or co_leaf != 'co_name' or \ str(repo) != expected_repo: raise GiveUp('Error in reading checkout back\n' ' co_dir %s, expected None\n' ' co_leaf %s, expected co_name\n' ' repo %s\n' ' expected %s'%(co_dir, co_leaf, repo, expected_repo)) if len(options) != 3 or \ options['Jim'] != False or \ options['Bill'] != 'Some sort of string' or \ options['Fred'] != 99: raise GiveUp('Error in reading checkout options back\n' " expected {'Jim': False, 'Bill': 'Some sort of string', 'Fred': 99}\n" ' got %s'%options)
def test_ReleaseStamp_basics(d): banner('RELEASE STAMP BASICS') banner('Write "empty" release file', 2) r0 = ReleaseStamp() r0.write_to_file('r1.release') check_release_file_starts('r1.release', '<REPLACE THIS>', '<REPLACE THIS>', 'tar', 'gzip', '', '', '') # We can read that as a normal VersionStamp banner('Read "empty" release file as stamp', 2) s = VersionStamp.from_file('r1.release') s.write_to_file('r1.stamp') check_stamp_file_starts('r1.stamp', '', '', '') # We can't read in r1.release as a release, because of the name and version banner('Read "empty" release file as release (it should fail)', 2) try: r1 = ReleaseStamp.from_file('r1.release') except GiveUp as e: if 'Release name "<REPLACE THIS>" is not allowed' not in str(e): raise GiveUp('Unexpected error reading r1.release: %s'%e) # We can't read in r1.stamp as a release, because of the name and version banner('Read "empty" stamp file as release (it should fail)', 2) try: r1 = ReleaseStamp.from_file('r1.stamp') except NoSectionError as e: if e.section != 'RELEASE': raise GiveUp('Expected section "RELEASE" to be missing, but got' ' NoSectionError for "%s"'%e.section) except Exception as e: raise GiveUp('Unexpected error reading r1.stamp: %s'%e) # We can't set a bad name, version, archive or compression try: r0.release_spec.name = '+++' except GiveUp as e: if 'Release name "+++" is not allowed' not in str(e): raise GiveUp('Unexpected error trying to write bad name: %s'%e) r0.release_spec.name = 'project99' try: r0.release_spec.version = '+++' except GiveUp as e: if 'Release version "+++" is not allowed' not in str(e): raise GiveUp('Unexpected error trying to write bad version: %s'%e) r0.release_spec.version = '1.2.3' try: r0.release_spec.archive = 'fred' except GiveUp as e: if 'Release archive "fred" is not allowed' not in str(e): raise GiveUp('Unexpected error trying to write bad version: %s'%e) r0.release_spec.archive = 'tar' try: r0.release_spec.compression = 'fred' except GiveUp as e: if 'Release compression "fred" is not allowed' not in str(e): raise GiveUp('Unexpected error trying to write bad version: %s'%e) r0.release_spec.compression = 'bzip2' r0.write_to_file('r2.release') # But when we get it right, it is OK check_release_file_starts('r2.release', 'project99', '1.2.3', 'tar', 'bzip2', '', '', '')
def write(our_stamp_file, far_stamp_file, output_dir_name): current_dir = os.getcwd() output_dir = os.path.join(current_dir, output_dir_name) output_dir = canonical_path(output_dir) if os.path.exists(output_dir): raise LocalError('Output directory %s already exists'%output_dir) if our_stamp_file == '-': our_stamp, problems = determine_our_stamp(current_dir) else: our_stamp = VersionStamp.from_file(our_stamp_file) far_stamp = VersionStamp.from_file(far_stamp_file) # Determine what has changed with respect to the "far" stamp # - those changes are what we need to apply to make it the same as us... deleted, new, changed, problems = far_stamp.compare_checkouts(our_stamp) # deleted = [ (label, co_dir, co_leaf, repo), ... ] # new = [ (label, co_dir, co_leaf, repo), ... ] # changed = [ (label, revision1, revision2), ... ] # problems = [ (label, summary-string), ... ] print print 'Summary: deleted %d, new %d, changed %d, problems %d'%(len(deleted), len(new), len(changed), len(problems)) print os.mkdir(output_dir) manifest_filename = os.path.join(output_dir, 'MANIFEST.txt') for label, rev1, rev2 in changed: print "-- Determining changes for checkout %s, %s..%s"%(label, rev1, rev2) co_dir, co_leaf, repo = our_stamp.checkouts[label] vcs = repo.vcs if vcs == 'bzr': bzr_send(label, co_dir, co_leaf, repo, rev1, rev2, output_dir, manifest_filename) elif vcs == 'svn': svn_diff(label, co_dir, co_leaf, repo, rev1, rev2, output_dir, manifest_filename) elif vcs == 'git': git_format_patch(label, co_dir, co_leaf, repo, rev1, rev2, output_dir, manifest_filename) else: print 'Unable to deal with VCS %s'%vcs continue # For deleted checkouts, we definitely don't want to do anything # - if they're not being used anymore, leaving them around will not # hurt, and it is the simplest and safest option. if deleted: print print 'The following checkouts were deleted' for label, co_dir, co_leaf, repo in deleted: print ' %s'%label if co_leaf: print ' %s'%(os.path.join(co_dir, co_leaf)) else: print ' %s'%co_dir print ' %s'%repo if repo.branch: print ' branch %s'%repo.branch if repo.revision: print ' branch %s'%repo.revision # TODO: For new checkouts, the best we can do is just to TAR up the # directory and copy it directly, and cross our fingers. We might as # well leave any VCS metadata intact. When restoring, it's probably # sensible to leave it up to the user to do a "muddle assert" of the # checked_out label, rather than try to second guess things... # ...so must remember to add a MANIFEST entry! # (if, at the other end, we're untarring a new checkout, we must check # if the directory already exists, and perhaps refuse to do it if so?) if new: for label, co_dir, co_leaf, repo in new: print "-- Saving tarfile for new checkout %s"%label print " Originally from" if co_leaf: print ' %s'%(os.path.join(co_dir, co_leaf)) else: print ' %s'%co_dir print ' %s'%repo if repo.branch: print ' branch %s'%repo.branch if repo.revision: print ' revision %s'%repo.revision tar_pack(label, co_dir, co_leaf, repo, output_dir, manifest_filename) if problems: print print 'There were the following problems' for tup in problems: print ' ',tup
def write(our_stamp_file, far_stamp_file, output_dir_name): current_dir = os.getcwd() output_dir = os.path.join(current_dir, output_dir_name) output_dir = canonical_path(output_dir) if os.path.exists(output_dir): raise LocalError('Output directory %s already exists' % output_dir) if our_stamp_file == '-': our_stamp, problems = determine_our_stamp(current_dir) else: our_stamp = VersionStamp.from_file(our_stamp_file) far_stamp = VersionStamp.from_file(far_stamp_file) # Determine what has changed with respect to the "far" stamp # - those changes are what we need to apply to make it the same as us... deleted, new, changed, problems = far_stamp.compare_checkouts(our_stamp) # deleted = [ (label, co_dir, co_leaf, repo), ... ] # new = [ (label, co_dir, co_leaf, repo), ... ] # changed = [ (label, revision1, revision2), ... ] # problems = [ (label, summary-string), ... ] print print 'Summary: deleted %d, new %d, changed %d, problems %d' % ( len(deleted), len(new), len(changed), len(problems)) print os.mkdir(output_dir) manifest_filename = os.path.join(output_dir, 'MANIFEST.txt') for label, rev1, rev2 in changed: print "-- Determining changes for checkout %s, %s..%s" % (label, rev1, rev2) co_dir, co_leaf, repo = our_stamp.checkouts[label] vcs = repo.vcs if vcs == 'bzr': bzr_send(label, co_dir, co_leaf, repo, rev1, rev2, output_dir, manifest_filename) elif vcs == 'svn': svn_diff(label, co_dir, co_leaf, repo, rev1, rev2, output_dir, manifest_filename) elif vcs == 'git': git_format_patch(label, co_dir, co_leaf, repo, rev1, rev2, output_dir, manifest_filename) else: print 'Unable to deal with VCS %s' % vcs continue # For deleted checkouts, we definitely don't want to do anything # - if they're not being used anymore, leaving them around will not # hurt, and it is the simplest and safest option. if deleted: print print 'The following checkouts were deleted' for label, co_dir, co_leaf, repo in deleted: print ' %s' % label if co_leaf: print ' %s' % (os.path.join(co_dir, co_leaf)) else: print ' %s' % co_dir print ' %s' % repo if repo.branch: print ' branch %s' % repo.branch if repo.revision: print ' branch %s' % repo.revision # TODO: For new checkouts, the best we can do is just to TAR up the # directory and copy it directly, and cross our fingers. We might as # well leave any VCS metadata intact. When restoring, it's probably # sensible to leave it up to the user to do a "muddle assert" of the # checked_out label, rather than try to second guess things... # ...so must remember to add a MANIFEST entry! # (if, at the other end, we're untarring a new checkout, we must check # if the directory already exists, and perhaps refuse to do it if so?) if new: for label, co_dir, co_leaf, repo in new: print "-- Saving tarfile for new checkout %s" % label print " Originally from" if co_leaf: print ' %s' % (os.path.join(co_dir, co_leaf)) else: print ' %s' % co_dir print ' %s' % repo if repo.branch: print ' branch %s' % repo.branch if repo.revision: print ' revision %s' % repo.revision tar_pack(label, co_dir, co_leaf, repo, output_dir, manifest_filename) if problems: print print 'There were the following problems' for tup in problems: print ' ', tup
def test_ReleaseStamp_basics(d): banner('RELEASE STAMP BASICS') banner('Write "empty" release file', 2) r0 = ReleaseStamp() r0.write_to_file('r1.release') check_release_file_starts('r1.release', '<REPLACE THIS>', '<REPLACE THIS>', 'tar', 'gzip', '', '', '') # We can read that as a normal VersionStamp banner('Read "empty" release file as stamp', 2) s = VersionStamp.from_file('r1.release') s.write_to_file('r1.stamp') check_stamp_file_starts('r1.stamp', '', '', '') # We can't read in r1.release as a release, because of the name and version banner('Read "empty" release file as release (it should fail)', 2) try: r1 = ReleaseStamp.from_file('r1.release') except GiveUp as e: if 'Release name "<REPLACE THIS>" is not allowed' not in str(e): raise GiveUp('Unexpected error reading r1.release: %s' % e) # We can't read in r1.stamp as a release, because of the name and version banner('Read "empty" stamp file as release (it should fail)', 2) try: r1 = ReleaseStamp.from_file('r1.stamp') except NoSectionError as e: if e.section != 'RELEASE': raise GiveUp('Expected section "RELEASE" to be missing, but got' ' NoSectionError for "%s"' % e.section) except Exception as e: raise GiveUp('Unexpected error reading r1.stamp: %s' % e) # We can't set a bad name, version, archive or compression try: r0.release_spec.name = '+++' except GiveUp as e: if 'Release name "+++" is not allowed' not in str(e): raise GiveUp('Unexpected error trying to write bad name: %s' % e) r0.release_spec.name = 'project99' try: r0.release_spec.version = '+++' except GiveUp as e: if 'Release version "+++" is not allowed' not in str(e): raise GiveUp('Unexpected error trying to write bad version: %s' % e) r0.release_spec.version = '1.2.3' try: r0.release_spec.archive = 'fred' except GiveUp as e: if 'Release archive "fred" is not allowed' not in str(e): raise GiveUp('Unexpected error trying to write bad version: %s' % e) r0.release_spec.archive = 'tar' try: r0.release_spec.compression = 'fred' except GiveUp as e: if 'Release compression "fred" is not allowed' not in str(e): raise GiveUp('Unexpected error trying to write bad version: %s' % e) r0.release_spec.compression = 'bzip2' r0.write_to_file('r2.release') # But when we get it right, it is OK check_release_file_starts('r2.release', 'project99', '1.2.3', 'tar', 'bzip2', '', '', '')