)]}'
{"etc/proxy-server.conf-sample":[{"author":{"_account_id":9625,"name":"Thiago da Silva","email":"thiagodasilva@gmail.com","username":"thiago"},"change_message_id":"18c55b0494abb3e400e0ba310e03f2bbe3d30739","unresolved":false,"context_lines":[{"line_number":1072,"context_line":"# in the container configuration file, which will be eventually"},{"line_number":1073,"context_line":"# deprecated. See documentation for more details."},{"line_number":1074,"context_line":"# allow_versioned_writes \u003d false"},{"line_number":1075,"context_line":"# The use_symlinks option should be enabled for new clusters, the default will"},{"line_number":1076,"context_line":"# change in a future release."},{"line_number":1077,"context_line":"# use_symlinks \u003d false"},{"line_number":1078,"context_line":""},{"line_number":1079,"context_line":"# Note: Put after auth and before dlo and slo middlewares."}],"source_content_type":"application/octet-stream","patch_set":15,"id":"7faddb67_af1e2b5c","line":1076,"range":{"start_line":1075,"start_character":2,"end_line":1076,"end_character":28},"updated":"2019-08-21 15:28:07.000000000","message":"I think we should expand this comment, it\u0027s a bit vague as is, leaving some un-answered quetions.\n\n\"only\" new clusters are supported?\nwhat happens if it\u0027s enabled for an existing cluster? \nWhen the default changes, will it support existing clusters too?","commit_id":"b2a7005bc7d9ba0610957e73e3f507731b146d2a"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"571fcc99eda5828d26575fba392cacf1fb36fc6d","unresolved":false,"context_lines":[{"line_number":1072,"context_line":"# in the container configuration file, which will be eventually"},{"line_number":1073,"context_line":"# deprecated. See documentation for more details."},{"line_number":1074,"context_line":"# allow_versioned_writes \u003d false"},{"line_number":1075,"context_line":"# The use_symlinks option should be enabled for new clusters, the default will"},{"line_number":1076,"context_line":"# change in a future release."},{"line_number":1077,"context_line":"# use_symlinks \u003d false"},{"line_number":1078,"context_line":""},{"line_number":1079,"context_line":"# Note: Put after auth and before dlo and slo middlewares."}],"source_content_type":"application/octet-stream","patch_set":15,"id":"7faddb67_30c825a7","line":1076,"range":{"start_line":1075,"start_character":2,"end_line":1076,"end_character":28},"in_reply_to":"7faddb67_af1e2b5c","updated":"2019-08-22 18:21:07.000000000","message":"Seconding this. Maybe something like\n\n\u003e Use symlinks to point to current versions in the archive container. This reduces data movement and removes race conditions that could lead to data loss when overwriting and deleting versioned data at a cost of increased time-to-first-byte on read. Note that this has impacts on usage stats and container quotas. Default is false to match preexisting behavior, but this may change in a future release.\n\nAs for your questions, my understanding is:\n\nExisting clusters can use this too, provided operators and users are aware of and expecting the new behavior.\n\nEnabling it for an existing cluster makes all of the existing versioned containers behave like they were freshly-enabled. That is to say, when a new write comes in, we\n- check if the current version is a VW symlink, see that it isn\u0027t,\n- transfer it to the archive container,\n- let the client write to the archive container, and\n- drop a link to the new write in the primary container.\n\nSo on the whole, it should be pretty seamless whenever we get around to switching the default. It\u0027s just a matter of setting expectations appropriately.","commit_id":"b2a7005bc7d9ba0610957e73e3f507731b146d2a"}],"swift/common/middleware/symlink.py":[{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"cdd9e9260f8230a2d1616eeb8d54207fb1f154fa","unresolved":false,"context_lines":[{"line_number":476,"context_line":"                raise LinkIterError()"},{"line_number":477,"context_line":"            # format: /\u003caccount name\u003e/\u003ccontainer name\u003e/\u003cobject name\u003e"},{"line_number":478,"context_line":"            new_req \u003d build_traversal_req(symlink_target)"},{"line_number":479,"context_line":"            if not self._response_header_value(SYMLOOP_EXTEND) \u003d\u003d \u0027true\u0027:"},{"line_number":480,"context_line":"                self._loop_count +\u003d 1"},{"line_number":481,"context_line":"            return self._recursive_get_head(new_req, target_etag\u003dresp_etag)"},{"line_number":482,"context_line":"        else:"}],"source_content_type":"text/x-python","patch_set":16,"id":"7faddb67_9fca5d17","line":479,"updated":"2019-08-21 20:45:52.000000000","message":"Oh, sneaky -- I like it! We should probably add something of a docstring for the constant though.\n\nAnd I feel like config_true_value might be nice -- remembering that it\u0027s *exactly* \u0027true\u0027 (not \u0027True\u0027 or \u0027TRUE\u0027 or \u0027yes\u0027 or \u00271\u0027 or ...) is a little annoying.","commit_id":"cbc9e052491a9dc36f6920489d6bb395d23d5533"},{"author":{"_account_id":9625,"name":"Thiago da Silva","email":"thiagodasilva@gmail.com","username":"thiago"},"change_message_id":"7dd41bf9853425e6fef14d9bdd5be5d5484144f3","unresolved":false,"context_lines":[{"line_number":476,"context_line":"                raise LinkIterError()"},{"line_number":477,"context_line":"            # format: /\u003caccount name\u003e/\u003ccontainer name\u003e/\u003cobject name\u003e"},{"line_number":478,"context_line":"            new_req \u003d build_traversal_req(symlink_target)"},{"line_number":479,"context_line":"            if not self._response_header_value(SYMLOOP_EXTEND) \u003d\u003d \u0027true\u0027:"},{"line_number":480,"context_line":"                self._loop_count +\u003d 1"},{"line_number":481,"context_line":"            return self._recursive_get_head(new_req, target_etag\u003dresp_etag)"},{"line_number":482,"context_line":"        else:"}],"source_content_type":"text/x-python","patch_set":16,"id":"7faddb67_8673ea4e","line":479,"in_reply_to":"7faddb67_9fca5d17","updated":"2019-08-22 12:12:29.000000000","message":"changed to use config_true_value","commit_id":"cbc9e052491a9dc36f6920489d6bb395d23d5533"}],"swift/common/middleware/versioned_writes.py":[{"author":{"_account_id":9625,"name":"Thiago da Silva","email":"thiagodasilva@gmail.com","username":"thiago"},"change_message_id":"98e69e862f8077f3867d0333e8516c819c662a3d","unresolved":false,"context_lines":[{"line_number":455,"context_line":"                put_req.headers[header] \u003d value"},{"line_number":456,"context_line":""},{"line_number":457,"context_line":"        # XXX: we just moved a *ton* of stuff over; would it be better to just"},{"line_number":458,"context_line":"        # change the path for the client request?? maybe has some troubles"},{"line_number":459,"context_line":"        # with ACLs on the versions container... might need to \"manually\" set"},{"line_number":460,"context_line":"        # the req as pre-authed..."},{"line_number":461,"context_line":""},{"line_number":462,"context_line":"        # do the write"}],"source_content_type":"text/x-python","patch_set":1,"id":"9fdfeff1_a2238ca6","line":459,"range":{"start_line":458,"start_character":51,"end_line":459,"end_character":45},"updated":"2019-02-01 10:47:51.000000000","message":"yeah, this is an interesting point because the ACL check should go against the original container name...","commit_id":"ae7138acecf3a22e0373a6806a8519bd4bf85a56"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"981273706a2c8128860ee551f73b236c71ca537e","unresolved":false,"context_lines":[{"line_number":572,"context_line":"                           object_name)"},{"line_number":573,"context_line":""},{"line_number":574,"context_line":"        if not self.use_symlinks:"},{"line_number":575,"context_line":"            return self.app"},{"line_number":576,"context_line":""},{"line_number":577,"context_line":"        req.ensure_x_timestamp()"},{"line_number":578,"context_line":"        put_resp, put_vers_obj_name, put_bytes \u003d self._put_versioned_obj_from_client("}],"source_content_type":"text/x-python","patch_set":1,"id":"9fdfeff1_cac29059","line":575,"updated":"2019-01-30 14:30:40.000000000","message":"does this reflect your opinion that the default versioned writes implementation should move to use_symlinks with the existing pop/copy migrated/deprecated?  Or is this purely for expediency as you flesh out more how symlinks versions work?","commit_id":"ae7138acecf3a22e0373a6806a8519bd4bf85a56"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"52a4c94e3d2f6c1417a4618d5569cc818bd24d8f","unresolved":false,"context_lines":[{"line_number":572,"context_line":"                           object_name)"},{"line_number":573,"context_line":""},{"line_number":574,"context_line":"        if not self.use_symlinks:"},{"line_number":575,"context_line":"            return self.app"},{"line_number":576,"context_line":""},{"line_number":577,"context_line":"        req.ensure_x_timestamp()"},{"line_number":578,"context_line":"        put_resp, put_vers_obj_name, put_bytes \u003d self._put_versioned_obj_from_client("}],"source_content_type":"text/x-python","patch_set":1,"id":"9fdfeff1_bacd1586","line":575,"in_reply_to":"9fdfeff1_cac29059","updated":"2019-01-30 18:31:55.000000000","message":"At the moment, I just left it as a config option to make it easier to play with the upgrade path from how data *used to be* laid out. Ultimately, users should *always* use symlinks if they can.\n\nThinking about it more, I think it\u0027s reasonable to simulate that by temporarily disabling versioning and just overwriting the VW symlink, though...","commit_id":"ae7138acecf3a22e0373a6806a8519bd4bf85a56"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"f3bca138fc1fd3ece26304ecfaf1ab8984f62a6a","unresolved":false,"context_lines":[{"line_number":494,"context_line":"        not_for_symlink_headers \u003d ("},{"line_number":495,"context_line":"            \u0027ETag\u0027, TGT_ACCT_SYMLINK_HDR, \u0027X-If-Delete-At\u0027,"},{"line_number":496,"context_line":"            \u0027X-Object-Manifest\u0027,"},{"line_number":497,"context_line":"        )"},{"line_number":498,"context_line":"        for header in not_for_symlink_headers:"},{"line_number":499,"context_line":"            req.headers.pop(header, None)"},{"line_number":500,"context_line":"        req.query_string \u003d \u0027symlink\u003dput\u0027"}],"source_content_type":"text/x-python","patch_set":4,"id":"7faddb67_9553406b","line":497,"updated":"2019-07-17 22:45:08.000000000","message":"might be other stuff that needs to go here - anything that belongs on the object and not the symlink...","commit_id":"6a7c667304920fae07d4161e6430f4f641bc54b0"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"63afffac98cc431a809e57a66c415c69a0c6f9b6","unresolved":false,"context_lines":[{"line_number":609,"context_line":"        target_etag \u003d put_resp.headers[\u0027Etag\u0027]"},{"line_number":610,"context_line":"        if \u0027HTTP_X_OBJECT_SYSMETA_SLO_ETAG\u0027 in req.environ:"},{"line_number":611,"context_line":"            target_etag \u003d \u0027\"%s\"\u0027 % req.environ["},{"line_number":612,"context_line":"                \u0027HTTP_X_OBJECT_SYSMETA_SLO_ETAG\u0027]"},{"line_number":613,"context_line":""},{"line_number":614,"context_line":"        return self._put_symlink_to_version(req, versions_cont,"},{"line_number":615,"context_line":"                                            put_vers_obj_name, api_version,"}],"source_content_type":"text/x-python","patch_set":4,"id":"7faddb67_715d6645","line":612,"updated":"2019-07-18 18:28:45.000000000","message":"we can use resolve_etag_is_at_header here I think","commit_id":"6a7c667304920fae07d4161e6430f4f641bc54b0"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"f3bca138fc1fd3ece26304ecfaf1ab8984f62a6a","unresolved":false,"context_lines":[{"line_number":704,"context_line":""},{"line_number":705,"context_line":"    def handle_obj_versions_delete_pop(self, req, versions_cont, api_version,"},{"line_number":706,"context_line":"                                       account_name, container_name,"},{"line_number":707,"context_line":"                                       object_name):"},{"line_number":708,"context_line":"        \"\"\""},{"line_number":709,"context_line":"        Handle DELETE requests when in stack mode."},{"line_number":710,"context_line":""}],"source_content_type":"text/x-python","patch_set":4,"id":"7faddb67_d55d3879","line":707,"updated":"2019-07-17 22:45:08.000000000","message":"it took a few tries to get this method write - i had tables drawn up and everything - see tests starting with:\n\ntest_stack_DELETE_...","commit_id":"6a7c667304920fae07d4161e6430f4f641bc54b0"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"f3bca138fc1fd3ece26304ecfaf1ab8984f62a6a","unresolved":false,"context_lines":[{"line_number":819,"context_line":"            if is_success(self._get_status_int()):"},{"line_number":820,"context_line":"                # TODO: should probably have further checks that this listing"},{"line_number":821,"context_line":"                # looks like JSON... but we\u0027re far enough right that we can"},{"line_number":822,"context_line":"                # probably trust it??"},{"line_number":823,"context_line":"                with closing_if_possible(app_resp):"},{"line_number":824,"context_line":"                    body \u003d b\u0027\u0027.join(app_resp)"},{"line_number":825,"context_line":"                try:"}],"source_content_type":"text/x-python","patch_set":4,"id":"7faddb67_3575acfa","line":822,"updated":"2019-07-17 22:45:08.000000000","message":"I did see a 4XX somewhere when a test returned a container listing with an empty string body instead of empty dict?","commit_id":"6a7c667304920fae07d4161e6430f4f641bc54b0"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"f3bca138fc1fd3ece26304ecfaf1ab8984f62a6a","unresolved":false,"context_lines":[{"line_number":848,"context_line":"                        item[\u0027hash\u0027] \u003d item.pop(\u0027symlink_etag\u0027) + \u0027\u0027.join("},{"line_number":849,"context_line":"                            \u0027; %s\u003d%s\u0027 % (k, v) for k, v in meta.items())"},{"line_number":850,"context_line":"                        # TODO: maybe include a ``del item[\u0027symlink_path\u0027]``?"},{"line_number":851,"context_line":"                        # but on GET you\u0027ll see the Content-Location anyway..."},{"line_number":852,"context_line":"                    body \u003d json.dumps(listing)"},{"line_number":853,"context_line":"                    self.update_content_length(len(body))"},{"line_number":854,"context_line":"                    app_resp \u003d [body]"}],"source_content_type":"text/x-python","patch_set":4,"id":"7faddb67_d58458d5","line":851,"updated":"2019-07-17 22:45:08.000000000","message":"probably can drop this","commit_id":"6a7c667304920fae07d4161e6430f4f641bc54b0"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"f3bca138fc1fd3ece26304ecfaf1ab8984f62a6a","unresolved":false,"context_lines":[{"line_number":1057,"context_line":"                except HTTPException as error_response:"},{"line_number":1058,"context_line":"                    return error_response(env, start_response)"},{"line_number":1059,"context_line":"        # TODO: on obj GET, look for symlink\u003dget and *manually* follow"},{"line_number":1060,"context_line":"        # the symlink if it\u0027s a VW symlink"},{"line_number":1061,"context_line":"        return self.app(env, start_response)"},{"line_number":1062,"context_line":""},{"line_number":1063,"context_line":""}],"source_content_type":"text/x-python","patch_set":4,"id":"7faddb67_157f50e0","line":1060,"updated":"2019-07-17 22:45:08.000000000","message":"This isn\u0027t done yet, and I\u0027m not sure it is valuable to do so.  People are going to \"know\" that versioned writes is using symlinks - the container listings say \"version_symlink\"\n\nI\u0027m just not sure I understand the use-case; it can\u0027t just be \"transparency\" because that\u0027s a non-goal.","commit_id":"6a7c667304920fae07d4161e6430f4f641bc54b0"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"f3bca138fc1fd3ece26304ecfaf1ab8984f62a6a","unresolved":false,"context_lines":[{"line_number":1070,"context_line":"    use_symlinks \u003d False"},{"line_number":1071,"context_line":"    if config_true_value(conf.get(\u0027allow_versioned_writes\u0027)):"},{"line_number":1072,"context_line":"        if \u0027use_symlinks\u0027 in conf:"},{"line_number":1073,"context_line":"            use_symlinks \u003d config_true_value(conf[\u0027use_symlinks\u0027])"},{"line_number":1074,"context_line":"            if use_symlinks and \u0027symlink\u0027 not in get_swift_info():"},{"line_number":1075,"context_line":"                logger.warning(\u0027symlink middleware is not enabled! Disabling \u0027"},{"line_number":1076,"context_line":"                               \u0027use_symlink in versioned_writes.\u0027)"}],"source_content_type":"text/x-python","patch_set":4,"id":"7faddb67_5542a8ac","line":1073,"updated":"2019-07-17 22:45:08.000000000","message":"need to add this to example configs","commit_id":"6a7c667304920fae07d4161e6430f4f641bc54b0"},{"author":{"_account_id":9625,"name":"Thiago da Silva","email":"thiagodasilva@gmail.com","username":"thiago"},"change_message_id":"eacd7fca1410bb362930bd64258ca4c5bb184225","unresolved":false,"context_lines":[{"line_number":551,"context_line":"        # check for any other errors"},{"line_number":552,"context_line":"        self._check_response_error(req, get_resp)"},{"line_number":553,"context_line":""},{"line_number":554,"context_line":"        if get_resp.headers.get(SYSMETA_VERSIONS_SYMLINK) \u003d\u003d \u0027true\u0027:"},{"line_number":555,"context_line":"            # existing object is a VW symlink; no action required"},{"line_number":556,"context_line":"            close_if_possible(get_resp.app_iter)"},{"line_number":557,"context_line":"            return"}],"source_content_type":"text/x-python","patch_set":5,"id":"7faddb67_df43f53d","line":554,"updated":"2019-07-19 15:51:41.000000000","message":"nice, so this is how we maintain backwards compatibility, if data in primary container is still an object, we copy it one last time, if it\u0027s already a symlink no data movement necessary...still too bad a GET is still required.","commit_id":"29ee9f17a2539fc681353cbeee8532e0cefbef98"},{"author":{"_account_id":9625,"name":"Thiago da Silva","email":"thiagodasilva@gmail.com","username":"thiago"},"change_message_id":"eacd7fca1410bb362930bd64258ca4c5bb184225","unresolved":false,"context_lines":[{"line_number":567,"context_line":"            object_name, ts_source)"},{"line_number":568,"context_line":""},{"line_number":569,"context_line":"        # store internal timestamp as version id to sysmeta"},{"line_number":570,"context_line":"        ver_id_header \u003d get_sys_meta_prefix(\u0027object\u0027) + \u0027version-id\u0027"},{"line_number":571,"context_line":"        get_resp.headers[ver_id_header] \u003d self._format_timestamp(ts_source)"},{"line_number":572,"context_line":""},{"line_number":573,"context_line":"        put_path_info \u003d \"/%s/%s/%s/%s\" % ("}],"source_content_type":"text/x-python","patch_set":5,"id":"7faddb67_ff3d91c3","line":570,"range":{"start_line":570,"start_character":8,"end_line":570,"end_character":21},"updated":"2019-07-19 15:51:41.000000000","message":"define constant?","commit_id":"29ee9f17a2539fc681353cbeee8532e0cefbef98"},{"author":{"_account_id":9625,"name":"Thiago da Silva","email":"thiagodasilva@gmail.com","username":"thiago"},"change_message_id":"7cb19e03d431864e0f66dcb94ac65c6cc1cf3cec","unresolved":false,"context_lines":[{"line_number":453,"context_line":"                put_req.headers[header] \u003d value"},{"line_number":454,"context_line":""},{"line_number":455,"context_line":"        # XXX: we just moved a *ton* of stuff over; would it be better to just"},{"line_number":456,"context_line":"        # change the path for the client request?? maybe has some troubles"},{"line_number":457,"context_line":"        # with ACLs on the versions container... might need to \"manually\" set"},{"line_number":458,"context_line":"        # the req as pre-authed..."},{"line_number":459,"context_line":"        if \u0027swift.content_type_overridden\u0027 in req.environ:"},{"line_number":460,"context_line":"            put_req.environ[\u0027swift.content_type_overridden\u0027] \u003d \\"}],"source_content_type":"text/x-python","patch_set":6,"id":"7faddb67_5fcdc5b4","line":457,"range":{"start_line":456,"start_character":51,"end_line":457,"end_character":45},"updated":"2019-07-19 17:38:04.000000000","message":"IIRC, we did have tests for a scenario where users would have access to write/delete to primary container but not versions container","commit_id":"8f43dfd4f8e0b5b11740e75955deff478e89c409"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"f040ca7b465ddfe5d9f8b9c3f50910250eb090c3","unresolved":false,"context_lines":[{"line_number":453,"context_line":"                put_req.headers[header] \u003d value"},{"line_number":454,"context_line":""},{"line_number":455,"context_line":"        # XXX: we just moved a *ton* of stuff over; would it be better to just"},{"line_number":456,"context_line":"        # change the path for the client request?? maybe has some troubles"},{"line_number":457,"context_line":"        # with ACLs on the versions container... might need to \"manually\" set"},{"line_number":458,"context_line":"        # the req as pre-authed..."},{"line_number":459,"context_line":"        if \u0027swift.content_type_overridden\u0027 in req.environ:"},{"line_number":460,"context_line":"            put_req.environ[\u0027swift.content_type_overridden\u0027] \u003d \\"}],"source_content_type":"text/x-python","patch_set":6,"id":"7faddb67_ad6b6c82","line":457,"range":{"start_line":456,"start_character":51,"end_line":457,"end_character":45},"in_reply_to":"7faddb67_5fcdc5b4","updated":"2019-07-19 21:04:51.000000000","message":"This was actually Tim\u0027s comment - and I had to add a couple more things to move over, but it seems to work.\n\nI think our goal would be functional equivalence, so after we\u0027re happy with the change and tests we can do a follow up to try doing this a different way and see if we think it\u0027s cleaner.","commit_id":"8f43dfd4f8e0b5b11740e75955deff478e89c409"},{"author":{"_account_id":9625,"name":"Thiago da Silva","email":"thiagodasilva@gmail.com","username":"thiago"},"change_message_id":"7cb19e03d431864e0f66dcb94ac65c6cc1cf3cec","unresolved":false,"context_lines":[{"line_number":481,"context_line":"        req.headers[TGT_ETAG_SYSMETA_SYMLINK_HDR] \u003d put_etag"},{"line_number":482,"context_line":"        req.headers[TGT_BYTES_SYSMETA_SYMLINK_HDR] \u003d put_bytes"},{"line_number":483,"context_line":"        req.headers[TGT_CONTENT_TYPE_SYSMETA_SYMLINK_HDR] \u003d \\"},{"line_number":484,"context_line":"            put_content_type"},{"line_number":485,"context_line":"        req.headers[TGT_OBJ_SYMLINK_HDR] \u003d wsgi_quote(\u0027%s/%s\u0027 % ("},{"line_number":486,"context_line":"            versions_cont, put_vers_obj_name))"},{"line_number":487,"context_line":"        req.headers[SYSMETA_VERSIONS_SYMLINK] \u003d \u0027true\u0027"}],"source_content_type":"text/x-python","patch_set":6,"id":"7faddb67_dfec55bc","line":484,"range":{"start_line":484,"start_character":12,"end_line":484,"end_character":28},"updated":"2019-07-19 17:38:04.000000000","message":"could you have used `req.headers[\u0027Content-Type\u0027]` ?","commit_id":"8f43dfd4f8e0b5b11740e75955deff478e89c409"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"f040ca7b465ddfe5d9f8b9c3f50910250eb090c3","unresolved":false,"context_lines":[{"line_number":481,"context_line":"        req.headers[TGT_ETAG_SYSMETA_SYMLINK_HDR] \u003d put_etag"},{"line_number":482,"context_line":"        req.headers[TGT_BYTES_SYSMETA_SYMLINK_HDR] \u003d put_bytes"},{"line_number":483,"context_line":"        req.headers[TGT_CONTENT_TYPE_SYSMETA_SYMLINK_HDR] \u003d \\"},{"line_number":484,"context_line":"            put_content_type"},{"line_number":485,"context_line":"        req.headers[TGT_OBJ_SYMLINK_HDR] \u003d wsgi_quote(\u0027%s/%s\u0027 % ("},{"line_number":486,"context_line":"            versions_cont, put_vers_obj_name))"},{"line_number":487,"context_line":"        req.headers[SYSMETA_VERSIONS_SYMLINK] \u003d \u0027true\u0027"}],"source_content_type":"text/x-python","patch_set":6,"id":"7faddb67_4d42f810","line":484,"range":{"start_line":484,"start_character":12,"end_line":484,"end_character":28},"in_reply_to":"7faddb67_dfec55bc","updated":"2019-07-19 21:04:51.000000000","message":"that req object gets passed around quite a bit; i\u0027m guessing in some code path it was no longer the Content-Type of the PUT so I had to plumb it explicitly... I\u0027m already rebased so I can\u0027t easily change it and run tests to see what fails; but I\u0027ll try to double check.","commit_id":"8f43dfd4f8e0b5b11740e75955deff478e89c409"},{"author":{"_account_id":9625,"name":"Thiago da Silva","email":"thiagodasilva@gmail.com","username":"thiago"},"change_message_id":"7cb19e03d431864e0f66dcb94ac65c6cc1cf3cec","unresolved":false,"context_lines":[{"line_number":566,"context_line":"        vers_obj_name \u003d self._build_versions_object_name("},{"line_number":567,"context_line":"            object_name, ts_source)"},{"line_number":568,"context_line":""},{"line_number":569,"context_line":"        # store internal timestamp as version id to sysmeta"},{"line_number":570,"context_line":"        ver_id_header \u003d get_sys_meta_prefix(\u0027object\u0027) + \u0027version-id\u0027"},{"line_number":571,"context_line":"        get_resp.headers[ver_id_header] \u003d self._format_timestamp(ts_source)"},{"line_number":572,"context_line":""}],"source_content_type":"text/x-python","patch_set":6,"id":"7faddb67_5f294534","line":569,"range":{"start_line":569,"start_character":10,"end_line":569,"end_character":59},"updated":"2019-07-19 17:38:04.000000000","message":"what\u0027s the plan with this? how do you expect this to be used? is this an s3api thing? also wondering why it was not used in `_put_versioned_obj_from_client` too","commit_id":"8f43dfd4f8e0b5b11740e75955deff478e89c409"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"f040ca7b465ddfe5d9f8b9c3f50910250eb090c3","unresolved":false,"context_lines":[{"line_number":566,"context_line":"        vers_obj_name \u003d self._build_versions_object_name("},{"line_number":567,"context_line":"            object_name, ts_source)"},{"line_number":568,"context_line":""},{"line_number":569,"context_line":"        # store internal timestamp as version id to sysmeta"},{"line_number":570,"context_line":"        ver_id_header \u003d get_sys_meta_prefix(\u0027object\u0027) + \u0027version-id\u0027"},{"line_number":571,"context_line":"        get_resp.headers[ver_id_header] \u003d self._format_timestamp(ts_source)"},{"line_number":572,"context_line":""}],"source_content_type":"text/x-python","patch_set":6,"id":"7faddb67_0dc3a08a","line":569,"range":{"start_line":569,"start_character":10,"end_line":569,"end_character":59},"in_reply_to":"7faddb67_5f294534","updated":"2019-07-19 21:04:51.000000000","message":"I\u0027m not sure... seems like the timestamp should be good enough?","commit_id":"8f43dfd4f8e0b5b11740e75955deff478e89c409"},{"author":{"_account_id":9625,"name":"Thiago da Silva","email":"thiagodasilva@gmail.com","username":"thiago"},"change_message_id":"7cb19e03d431864e0f66dcb94ac65c6cc1cf3cec","unresolved":false,"context_lines":[{"line_number":580,"context_line":"    def handle_obj_versions_put(self, req, versions_cont, api_version,"},{"line_number":581,"context_line":"                                account_name, object_name):"},{"line_number":582,"context_line":"        \"\"\""},{"line_number":583,"context_line":"        Copy current version of object to versions_container before proceeding"},{"line_number":584,"context_line":"        with original request."},{"line_number":585,"context_line":""},{"line_number":586,"context_line":"        :param req: original request."},{"line_number":587,"context_line":"        :param versions_cont: container where previous versions of the object"}],"source_content_type":"text/x-python","patch_set":6,"id":"7faddb67_bfc39937","line":584,"range":{"start_line":583,"start_character":8,"end_line":584,"end_character":30},"updated":"2019-07-19 17:38:04.000000000","message":"please update docstring...","commit_id":"8f43dfd4f8e0b5b11740e75955deff478e89c409"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"f040ca7b465ddfe5d9f8b9c3f50910250eb090c3","unresolved":false,"context_lines":[{"line_number":580,"context_line":"    def handle_obj_versions_put(self, req, versions_cont, api_version,"},{"line_number":581,"context_line":"                                account_name, object_name):"},{"line_number":582,"context_line":"        \"\"\""},{"line_number":583,"context_line":"        Copy current version of object to versions_container before proceeding"},{"line_number":584,"context_line":"        with original request."},{"line_number":585,"context_line":""},{"line_number":586,"context_line":"        :param req: original request."},{"line_number":587,"context_line":"        :param versions_cont: container where previous versions of the object"}],"source_content_type":"text/x-python","patch_set":6,"id":"7faddb67_6dd49448","line":584,"range":{"start_line":583,"start_character":8,"end_line":584,"end_character":30},"in_reply_to":"7faddb67_bfc39937","updated":"2019-07-19 21:04:51.000000000","message":"#willfix","commit_id":"8f43dfd4f8e0b5b11740e75955deff478e89c409"},{"author":{"_account_id":9625,"name":"Thiago da Silva","email":"thiagodasilva@gmail.com","username":"thiago"},"change_message_id":"7cb19e03d431864e0f66dcb94ac65c6cc1cf3cec","unresolved":false,"context_lines":[{"line_number":603,"context_line":"                                                object_name)"},{"line_number":604,"context_line":""},{"line_number":605,"context_line":"        target_etag \u003d put_resp.headers[\u0027Etag\u0027]"},{"line_number":606,"context_line":"        if \u0027HTTP_X_OBJECT_SYSMETA_SLO_ETAG\u0027 in req.environ:"},{"line_number":607,"context_line":"            target_etag \u003d \u0027\"%s\"\u0027 % req.environ["},{"line_number":608,"context_line":"                \u0027HTTP_X_OBJECT_SYSMETA_SLO_ETAG\u0027]"},{"line_number":609,"context_line":""}],"source_content_type":"text/x-python","patch_set":6,"id":"7faddb67_df1a15c4","line":606,"updated":"2019-07-19 17:38:04.000000000","message":"wondering if we could make use of `resolve_etag_is_at_header` to not leak SLO here? maybe??","commit_id":"8f43dfd4f8e0b5b11740e75955deff478e89c409"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"f040ca7b465ddfe5d9f8b9c3f50910250eb090c3","unresolved":false,"context_lines":[{"line_number":603,"context_line":"                                                object_name)"},{"line_number":604,"context_line":""},{"line_number":605,"context_line":"        target_etag \u003d put_resp.headers[\u0027Etag\u0027]"},{"line_number":606,"context_line":"        if \u0027HTTP_X_OBJECT_SYSMETA_SLO_ETAG\u0027 in req.environ:"},{"line_number":607,"context_line":"            target_etag \u003d \u0027\"%s\"\u0027 % req.environ["},{"line_number":608,"context_line":"                \u0027HTTP_X_OBJECT_SYSMETA_SLO_ETAG\u0027]"},{"line_number":609,"context_line":""}],"source_content_type":"text/x-python","patch_set":6,"id":"7faddb67_cddfc863","line":606,"in_reply_to":"7faddb67_df1a15c4","updated":"2019-07-19 21:04:51.000000000","message":"yeah I think we\u0027ll get rid of the leak on rebase when we start making hardlinks to manifests always use the manifest etag","commit_id":"8f43dfd4f8e0b5b11740e75955deff478e89c409"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"f040ca7b465ddfe5d9f8b9c3f50910250eb090c3","unresolved":false,"context_lines":[{"line_number":744,"context_line":"                    # is also a DELETE, we need only to roll back the top of"},{"line_number":745,"context_line":"                    # the queue by clearing one marker"},{"line_number":746,"context_line":"                    cleanup_obj_name \u003d bytes_to_wsgi("},{"line_number":747,"context_line":"                        previous_version[\u0027name\u0027].encode(\u0027utf-8\u0027))"},{"line_number":748,"context_line":"                else:"},{"line_number":749,"context_line":"                    # the current version is something in the root container,"},{"line_number":750,"context_line":"                    # and the previous version was this DELETE marker, we need"}],"source_content_type":"text/x-python","patch_set":6,"id":"7faddb67_edde446b","line":747,"updated":"2019-07-19 21:04:51.000000000","message":"well, *here* we set cleanup_obj_name and don\u0027t seem to care if the head is a symlink... but in this branch the \"most recent version\" is a delete marker - so quite different than the test below...","commit_id":"8f43dfd4f8e0b5b11740e75955deff478e89c409"},{"author":{"_account_id":9625,"name":"Thiago da Silva","email":"thiagodasilva@gmail.com","username":"thiago"},"change_message_id":"7cb19e03d431864e0f66dcb94ac65c6cc1cf3cec","unresolved":false,"context_lines":[{"line_number":759,"context_line":"                        \u0027%s/%s\u0027 % (versions_cont, prev_obj_name)):"},{"line_number":760,"context_line":"                    # if current version is VW symlink and target is"},{"line_number":761,"context_line":"                    # previous_version"},{"line_number":762,"context_line":"                    cleanup_obj_name \u003d prev_obj_name"},{"line_number":763,"context_line":"                    continue"},{"line_number":764,"context_line":"                # replace the current version with a symlink, regardless"},{"line_number":765,"context_line":"                target_etag \u003d previous_version[\u0027hash\u0027]"}],"source_content_type":"text/x-python","patch_set":6,"id":"7faddb67_2a920558","line":762,"range":{"start_line":762,"start_character":20,"end_line":762,"end_character":36},"updated":"2019-07-19 17:38:04.000000000","message":"if the current object is not a symlink, clean_obj_name is not set, is it?\n\nconfirmed with the test below:\n\nbefore upgrade:\n- swift post versions\n- swift post c1 -H \u0027X-Versions-Location: versions`\n- swift upload c1 obj\n- swift upload c1 obj\n- swift upload c1 obj\n- swift upload c1 obj\n\nAt this point versions container should have 3 versions of \u0027obj\u0027, for sanity testing:\n\n- swift delete c1 obj\n\nVersions should have 2 versions of \u0027obj\u0027\n\nNow, upgrade to this patch and issue delete:\n\n- swift delete c1 obj\n\nVersions should have 1 version of \u0027obj\u0027, but it still has 2, with symlink pointing to the most recent.","commit_id":"8f43dfd4f8e0b5b11740e75955deff478e89c409"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"f040ca7b465ddfe5d9f8b9c3f50910250eb090c3","unresolved":false,"context_lines":[{"line_number":759,"context_line":"                        \u0027%s/%s\u0027 % (versions_cont, prev_obj_name)):"},{"line_number":760,"context_line":"                    # if current version is VW symlink and target is"},{"line_number":761,"context_line":"                    # previous_version"},{"line_number":762,"context_line":"                    cleanup_obj_name \u003d prev_obj_name"},{"line_number":763,"context_line":"                    continue"},{"line_number":764,"context_line":"                # replace the current version with a symlink, regardless"},{"line_number":765,"context_line":"                target_etag \u003d previous_version[\u0027hash\u0027]"}],"source_content_type":"text/x-python","patch_set":6,"id":"7faddb67_cd8a6862","line":762,"range":{"start_line":762,"start_character":20,"end_line":762,"end_character":36},"in_reply_to":"7faddb67_2a920558","updated":"2019-07-19 21:04:51.000000000","message":"I think the description of your test matches my understanding as well.\n\nI know cleanup_obj_name will only ever remove things in the versions container.","commit_id":"8f43dfd4f8e0b5b11740e75955deff478e89c409"},{"author":{"_account_id":9625,"name":"Thiago da Silva","email":"thiagodasilva@gmail.com","username":"thiago"},"change_message_id":"7cb19e03d431864e0f66dcb94ac65c6cc1cf3cec","unresolved":false,"context_lines":[{"line_number":1005,"context_line":"            req.environ[\u0027swift.source\u0027] \u003d \u0027VW\u0027"},{"line_number":1006,"context_line":"            # we\u0027ve changed the path and don\u0027t want any override going on"},{"line_number":1007,"context_line":"            req.environ.pop(\u0027HTTP_X_BACKEND_STORAGE_POLICY_INDEX\u0027, None)"},{"line_number":1008,"context_line":"            resp \u003d req.get_response(self.app)"},{"line_number":1009,"context_line":"        return resp"},{"line_number":1010,"context_line":""},{"line_number":1011,"context_line":"    def __call__(self, env, start_response):"}],"source_content_type":"text/x-python","patch_set":6,"id":"7faddb67_ca57b125","line":1008,"range":{"start_line":1008,"start_character":12,"end_line":1008,"end_character":45},"updated":"2019-07-19 17:38:04.000000000","message":"what if users doesn\u0027t have write ACLs to versions location? maybe use a pre_auth_request?","commit_id":"8f43dfd4f8e0b5b11740e75955deff478e89c409"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"f040ca7b465ddfe5d9f8b9c3f50910250eb090c3","unresolved":false,"context_lines":[{"line_number":1005,"context_line":"            req.environ[\u0027swift.source\u0027] \u003d \u0027VW\u0027"},{"line_number":1006,"context_line":"            # we\u0027ve changed the path and don\u0027t want any override going on"},{"line_number":1007,"context_line":"            req.environ.pop(\u0027HTTP_X_BACKEND_STORAGE_POLICY_INDEX\u0027, None)"},{"line_number":1008,"context_line":"            resp \u003d req.get_response(self.app)"},{"line_number":1009,"context_line":"        return resp"},{"line_number":1010,"context_line":""},{"line_number":1011,"context_line":"    def __call__(self, env, start_response):"}],"source_content_type":"text/x-python","patch_set":6,"id":"7faddb67_cdfb48bb","line":1008,"range":{"start_line":1008,"start_character":12,"end_line":1008,"end_character":45},"in_reply_to":"7faddb67_ca57b125","updated":"2019-07-19 21:04:51.000000000","message":"I\u0027ll see if I can extend test_versioning_container_acl to check that functionality - thanks!","commit_id":"8f43dfd4f8e0b5b11740e75955deff478e89c409"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"0226346303630ebb6f88390acc031316ac6a2e1a","unresolved":false,"context_lines":[{"line_number":444,"context_line":"        req.body \u003d b\u0027\u0027"},{"line_number":445,"context_line":"        # move metadata over, including sysmeta"},{"line_number":446,"context_line":"        for header, value in req.headers.items():"},{"line_number":447,"context_line":"            # XXX: what do we want for x-delete-at/after behavior?"},{"line_number":448,"context_line":"            if header.lower() in (\u0027x-static-large-object\u0027, \u0027content-type\u0027,"},{"line_number":449,"context_line":"                                  \u0027x-symlink-target\u0027,"},{"line_number":450,"context_line":"                                  \u0027x-object-manifest\u0027, \u0027etag\u0027) or \\"}],"source_content_type":"text/x-python","patch_set":8,"id":"7faddb67_df7b9cf1","line":447,"updated":"2019-07-25 20:37:28.000000000","message":"I\u0027m really not sure what to do here, I have no opinions how x-delete-at should interact with versioned containers...\n\nthe most implementable option would probably be to stick them on the target object going into the versions container (because at least the uri will stay the same) and then come what may...","commit_id":"10d64be4f9f63fa8af122aae2d9fee76027587f5"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"0226346303630ebb6f88390acc031316ac6a2e1a","unresolved":false,"context_lines":[{"line_number":455,"context_line":"        # XXX: we just moved a *ton* of stuff over; would it be better to just"},{"line_number":456,"context_line":"        # change the path for the client request?? maybe has some troubles"},{"line_number":457,"context_line":"        # with ACLs on the versions container... might need to \"manually\" set"},{"line_number":458,"context_line":"        # the req as pre-authed..."},{"line_number":459,"context_line":"        if \u0027swift.content_type_overridden\u0027 in req.environ:"},{"line_number":460,"context_line":"            put_req.environ[\u0027swift.content_type_overridden\u0027] \u003d \\"},{"line_number":461,"context_line":"                req.environ[\u0027swift.content_type_overridden\u0027]"}],"source_content_type":"text/x-python","patch_set":8,"id":"7faddb67_ff7538fb","line":458,"updated":"2019-07-25 20:37:28.000000000","message":"I\u0027m really not sure what\u0027s worse, but with a strong functional test suite in place I\u0027m at least confident we could take a stab at writing it both ways and pick what feels less gross","commit_id":"10d64be4f9f63fa8af122aae2d9fee76027587f5"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"0226346303630ebb6f88390acc031316ac6a2e1a","unresolved":false,"context_lines":[{"line_number":490,"context_line":"            \u0027ETag\u0027, TGT_ACCT_SYMLINK_HDR, \u0027X-If-Delete-At\u0027,"},{"line_number":491,"context_line":"            \u0027X-Object-Manifest\u0027, \u0027X-Static-Large-Object\u0027,"},{"line_number":492,"context_line":"            \u0027X-Object-Sysmeta-Slo-Etag\u0027, \u0027X-Object-Sysmeta-Slo-Size\u0027,"},{"line_number":493,"context_line":"        )"},{"line_number":494,"context_line":"        for header in not_for_symlink_headers:"},{"line_number":495,"context_line":"            req.headers.pop(header, None)"},{"line_number":496,"context_line":"        req.query_string \u003d \u0027symlink\u003dput\u0027"}],"source_content_type":"text/x-python","patch_set":8,"id":"7faddb67_bf61003c","line":493,"updated":"2019-07-25 20:37:28.000000000","message":"OMG the leakage, some of these might have constants we could borrow.","commit_id":"10d64be4f9f63fa8af122aae2d9fee76027587f5"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"0226346303630ebb6f88390acc031316ac6a2e1a","unresolved":false,"context_lines":[{"line_number":607,"context_line":"        target_etag \u003d put_resp.headers[\u0027Etag\u0027]"},{"line_number":608,"context_line":"        # if \u0027HTTP_X_OBJECT_SYSMETA_SLO_ETAG\u0027 in req.environ:"},{"line_number":609,"context_line":"        #     target_etag \u003d \u0027\"%s\"\u0027 % req.environ["},{"line_number":610,"context_line":"        #         \u0027HTTP_X_OBJECT_SYSMETA_SLO_ETAG\u0027]"},{"line_number":611,"context_line":""},{"line_number":612,"context_line":"        return self._put_symlink_to_version(req, versions_cont,"},{"line_number":613,"context_line":"                                            put_vers_obj_name, api_version,"}],"source_content_type":"text/x-python","patch_set":8,"id":"7faddb67_9f5e8474","line":610,"updated":"2019-07-25 20:37:28.000000000","message":"clean this up","commit_id":"10d64be4f9f63fa8af122aae2d9fee76027587f5"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"0226346303630ebb6f88390acc031316ac6a2e1a","unresolved":false,"context_lines":[{"line_number":778,"context_line":"                    # we actually have no idea how big the manifest is because"},{"line_number":779,"context_line":"                    # the container server lost it for us, but the client will"},{"line_number":780,"context_line":"                    # never see this value anyway"},{"line_number":781,"context_line":"                    put_bytes \u003d 0"},{"line_number":782,"context_line":"                resp \u003d self._put_symlink_to_version("},{"line_number":783,"context_line":"                    req, versions_cont, prev_obj_name, api_version,"},{"line_number":784,"context_line":"                    account_name, object_name, target_etag,"}],"source_content_type":"text/x-python","patch_set":8,"id":"7faddb67_ff4e98bf","line":781,"updated":"2019-07-25 20:37:28.000000000","message":"so much leakage!!!","commit_id":"10d64be4f9f63fa8af122aae2d9fee76027587f5"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"0226346303630ebb6f88390acc031316ac6a2e1a","unresolved":false,"context_lines":[{"line_number":853,"context_line":"                        _, meta \u003d parse_header(item[\u0027hash\u0027])"},{"line_number":854,"context_line":"                        tgt_bytes \u003d int(item.pop(\u0027symlink_bytes\u0027))"},{"line_number":855,"context_line":"                        if \u0027slo_etag\u0027 not in meta:"},{"line_number":856,"context_line":"                            item[\u0027bytes\u0027] \u003d tgt_bytes"},{"line_number":857,"context_line":"                        item[\u0027version_symlink\u0027] \u003d True"},{"line_number":858,"context_line":"                        item[\u0027hash\u0027] \u003d item.pop(\u0027symlink_etag\u0027) + \u0027\u0027.join("},{"line_number":859,"context_line":"                            \u0027; %s\u003d%s\u0027 % (k, v) for k, v in meta.items())"}],"source_content_type":"text/x-python","patch_set":8,"id":"7faddb67_dfc95c25","line":856,"updated":"2019-07-25 20:37:28.000000000","message":"this isn\u0027t a middleware leakage, this knowledge is down in the container server \n\nhttps://github.com/openstack/swift/blob/master/swift/container/server.py#L564","commit_id":"10d64be4f9f63fa8af122aae2d9fee76027587f5"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"0226346303630ebb6f88390acc031316ac6a2e1a","unresolved":false,"context_lines":[{"line_number":858,"context_line":"                        item[\u0027hash\u0027] \u003d item.pop(\u0027symlink_etag\u0027) + \u0027\u0027.join("},{"line_number":859,"context_line":"                            \u0027; %s\u003d%s\u0027 % (k, v) for k, v in meta.items())"},{"line_number":860,"context_line":"                        # TODO: maybe include a ``del item[\u0027symlink_path\u0027]``?"},{"line_number":861,"context_line":"                        # but on GET you\u0027ll see the Content-Location anyway..."},{"line_number":862,"context_line":"                    body \u003d json.dumps(listing).encode(\u0027ascii\u0027)"},{"line_number":863,"context_line":"                    self.update_content_length(len(body))"},{"line_number":864,"context_line":"                    app_resp \u003d [body]"}],"source_content_type":"text/x-python","patch_set":8,"id":"7faddb67_1f4a94ab","line":861,"updated":"2019-07-25 20:37:28.000000000","message":"I want to keep symlink_path","commit_id":"10d64be4f9f63fa8af122aae2d9fee76027587f5"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"0226346303630ebb6f88390acc031316ac6a2e1a","unresolved":false,"context_lines":[{"line_number":1067,"context_line":"                except HTTPException as error_response:"},{"line_number":1068,"context_line":"                    return error_response(env, start_response)"},{"line_number":1069,"context_line":"        # TODO: on obj GET, look for symlink\u003dget and *manually* follow"},{"line_number":1070,"context_line":"        # the symlink if it\u0027s a VW symlink"},{"line_number":1071,"context_line":"        return self.app(env, start_response)"},{"line_number":1072,"context_line":""},{"line_number":1073,"context_line":""}],"source_content_type":"text/x-python","patch_set":8,"id":"7faddb67_7f9e2808","line":1070,"updated":"2019-07-25 20:37:28.000000000","message":"I think not worth it, versioned writes means your object is a hardlink to a symlink - sorry, not sorry","commit_id":"10d64be4f9f63fa8af122aae2d9fee76027587f5"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"fbcc842c304679585740f4ed4164923b3aced748","unresolved":false,"context_lines":[{"line_number":750,"context_line":"                prev_obj_name \u003d bytes_to_wsgi("},{"line_number":751,"context_line":"                    previous_version[\u0027name\u0027].encode(\u0027utf-8\u0027))"},{"line_number":752,"context_line":"                if symlink_target \u003d\u003d wsgi_quote("},{"line_number":753,"context_line":"                        \u0027%s/%s\u0027 % (versions_cont, prev_obj_name)):"},{"line_number":754,"context_line":"                    # if current version is VW symlink and target is"},{"line_number":755,"context_line":"                    # previous_version"},{"line_number":756,"context_line":"                    cleanup_obj_name \u003d prev_obj_name"}],"source_content_type":"text/x-python","patch_set":9,"id":"7faddb67_11ff84ab","line":753,"updated":"2019-08-01 17:42:39.000000000","message":"with all the quoting trouble I\u0027ve had comparing non-ascii url escaped paths under py2 vs py3 in other places - I seriously wonder if this is functionally correct","commit_id":"009ebede372747410b242e46c70d2ce431f9ad46"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"fbcc842c304679585740f4ed4164923b3aced748","unresolved":false,"context_lines":[{"line_number":769,"context_line":"                    req.environ[\u0027swift.content_type_overridden\u0027] \u003d True"},{"line_number":770,"context_line":"                    # we actually have no idea how big the manifest is because"},{"line_number":771,"context_line":"                    # the container server lost it for us, but the client will"},{"line_number":772,"context_line":"                    # never see this value anyway"},{"line_number":773,"context_line":"                    put_bytes \u003d 0"},{"line_number":774,"context_line":"                resp \u003d self._put_symlink_to_version("},{"line_number":775,"context_line":"                    req, versions_cont, prev_obj_name, api_version,"}],"source_content_type":"text/x-python","patch_set":9,"id":"7faddb67_1147844e","line":772,"updated":"2019-08-01 17:42:39.000000000","message":"the fact that the db knows how many bytes the manifest object is, but doesn\u0027t return it in the listing is *really* annoying\n\nI feel like we could try to fix this by moving swift_bytes into the etag where it belongs and getting the container server to stop doing translations once it can trust the proxies are upgraded :shrug:","commit_id":"009ebede372747410b242e46c70d2ce431f9ad46"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"f699c87cdeaad7bf37d5abaef441e2451f75a0e1","unresolved":false,"context_lines":[{"line_number":834,"context_line":"                            item[\u0027symlink_path\u0027], 4, 4, True)"},{"line_number":835,"context_line":"                        if six.PY2:"},{"line_number":836,"context_line":"                            tgt_container \u003d tgt_container.encode(\u0027utf8\u0027)"},{"line_number":837,"context_line":"                        if unquote(tgt_container) !\u003d unquote(location):"},{"line_number":838,"context_line":"                            self.logger.debug(\u0027Found non-version symlink to \u0027"},{"line_number":839,"context_line":"                                              \u0027%r instead of %r\u0027,"},{"line_number":840,"context_line":"                                              tgt_container, location)"}],"source_content_type":"text/x-python","patch_set":9,"id":"7faddb67_4dd374d6","line":837,"updated":"2019-07-26 19:51:41.000000000","message":"I tried so many times to find a cleaner way to write this...","commit_id":"009ebede372747410b242e46c70d2ce431f9ad46"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"87ab88b82b9057b3882209b28f3f2999cc9150c5","unresolved":false,"context_lines":[{"line_number":837,"context_line":"                        if unquote(tgt_container) !\u003d unquote(location):"},{"line_number":838,"context_line":"                            self.logger.debug(\u0027Found non-version symlink to \u0027"},{"line_number":839,"context_line":"                                              \u0027%r instead of %r\u0027,"},{"line_number":840,"context_line":"                                              tgt_container, location)"},{"line_number":841,"context_line":"                            # if the archive container changed, leave the extra"},{"line_number":842,"context_line":"                            # info unmolested"},{"line_number":843,"context_line":"                            continue"}],"source_content_type":"text/x-python","patch_set":9,"id":"7faddb67_d2c0607f","line":840,"updated":"2019-07-26 21:56:16.000000000","message":"This is totally expected behavior, though, yeah? Like if clients create a hardlink in the container before turning on versioning...","commit_id":"009ebede372747410b242e46c70d2ce431f9ad46"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"fbcc842c304679585740f4ed4164923b3aced748","unresolved":false,"context_lines":[{"line_number":837,"context_line":"                        if unquote(tgt_container) !\u003d unquote(location):"},{"line_number":838,"context_line":"                            self.logger.debug(\u0027Found non-version symlink to \u0027"},{"line_number":839,"context_line":"                                              \u0027%r instead of %r\u0027,"},{"line_number":840,"context_line":"                                              tgt_container, location)"},{"line_number":841,"context_line":"                            # if the archive container changed, leave the extra"},{"line_number":842,"context_line":"                            # info unmolested"},{"line_number":843,"context_line":"                            continue"}],"source_content_type":"text/x-python","patch_set":9,"id":"7faddb67_861fbb6a","line":840,"in_reply_to":"7faddb67_d2c0607f","updated":"2019-08-01 17:42:39.000000000","message":"I think you\u0027re suggesting we could/should remove the debug line?  That\u0027s fine.  It\u0027s here not because I thought the situation was particularlly noteworthy (N.B. it\u0027s a *debug* level) but specifically because I had SO MANY problems with the listing returning symlinks w/o doing the appropriate key translations and like... you\u0027d get a DLO w/ a zero byte body and it was really hard to.... DEBUG!\n\nPerhaps this means we need to annotate versioned writes symlinks in the container listing more explicitly?  I\u0027m not sure...","commit_id":"009ebede372747410b242e46c70d2ce431f9ad46"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"fbcc842c304679585740f4ed4164923b3aced748","unresolved":false,"context_lines":[{"line_number":844,"context_line":"                        _, meta \u003d parse_header(item[\u0027hash\u0027])"},{"line_number":845,"context_line":"                        tgt_bytes \u003d int(item.pop(\u0027symlink_bytes\u0027))"},{"line_number":846,"context_line":"                        if \u0027slo_etag\u0027 not in meta:"},{"line_number":847,"context_line":"                            item[\u0027bytes\u0027] \u003d tgt_bytes"},{"line_number":848,"context_line":"                        item[\u0027version_symlink\u0027] \u003d True"},{"line_number":849,"context_line":"                        item[\u0027hash\u0027] \u003d item.pop(\u0027symlink_etag\u0027) + \u0027\u0027.join("},{"line_number":850,"context_line":"                            \u0027; %s\u003d%s\u0027 % (k, v) for k, v in meta.items())"}],"source_content_type":"text/x-python","patch_set":9,"id":"7faddb67_f16508b6","line":847,"updated":"2019-08-01 17:42:39.000000000","message":"right, if this symlink points to an slo manifest the container-server already \"fixed\" bytes","commit_id":"009ebede372747410b242e46c70d2ce431f9ad46"},{"author":{"_account_id":9625,"name":"Thiago da Silva","email":"thiagodasilva@gmail.com","username":"thiago"},"change_message_id":"18c55b0494abb3e400e0ba310e03f2bbe3d30739","unresolved":false,"context_lines":[{"line_number":529,"context_line":"        )"},{"line_number":530,"context_line":"        for header in not_for_symlink_headers:"},{"line_number":531,"context_line":"            req.headers.pop(header, None)"},{"line_number":532,"context_line":"        req.query_string \u003d \u0027symlink\u003dput\u0027"},{"line_number":533,"context_line":"        # *do* set swift_source here; this PUT is an implementation detail"},{"line_number":534,"context_line":"        req.environ[\u0027swift.source\u0027] \u003d \u0027VW\u0027"},{"line_number":535,"context_line":"        req.body \u003d b\u0027\u0027"}],"source_content_type":"text/x-python","patch_set":15,"id":"7faddb67_384b4a2b","line":532,"range":{"start_line":532,"start_character":8,"end_line":532,"end_character":40},"updated":"2019-08-21 15:28:07.000000000","message":"this query_string is not needed.","commit_id":"b2a7005bc7d9ba0610957e73e3f507731b146d2a"},{"author":{"_account_id":9625,"name":"Thiago da Silva","email":"thiagodasilva@gmail.com","username":"thiago"},"change_message_id":"7dd41bf9853425e6fef14d9bdd5be5d5484144f3","unresolved":false,"context_lines":[{"line_number":529,"context_line":"        )"},{"line_number":530,"context_line":"        for header in not_for_symlink_headers:"},{"line_number":531,"context_line":"            req.headers.pop(header, None)"},{"line_number":532,"context_line":"        req.query_string \u003d \u0027symlink\u003dput\u0027"},{"line_number":533,"context_line":"        # *do* set swift_source here; this PUT is an implementation detail"},{"line_number":534,"context_line":"        req.environ[\u0027swift.source\u0027] \u003d \u0027VW\u0027"},{"line_number":535,"context_line":"        req.body \u003d b\u0027\u0027"}],"source_content_type":"text/x-python","patch_set":15,"id":"7faddb67_e934f1e1","line":532,"range":{"start_line":532,"start_character":8,"end_line":532,"end_character":40},"in_reply_to":"7faddb67_384b4a2b","updated":"2019-08-22 12:12:29.000000000","message":"Done","commit_id":"b2a7005bc7d9ba0610957e73e3f507731b146d2a"},{"author":{"_account_id":9625,"name":"Thiago da Silva","email":"thiagodasilva@gmail.com","username":"thiago"},"change_message_id":"18c55b0494abb3e400e0ba310e03f2bbe3d30739","unresolved":false,"context_lines":[{"line_number":600,"context_line":"        vers_obj_name \u003d self._build_versions_object_name("},{"line_number":601,"context_line":"            object_name, ts_source)"},{"line_number":602,"context_line":""},{"line_number":603,"context_line":"        # store internal timestamp as version id to sysmeta"},{"line_number":604,"context_line":"        ver_id_header \u003d get_sys_meta_prefix(\u0027object\u0027) + \u0027version-id\u0027"},{"line_number":605,"context_line":"        get_resp.headers[ver_id_header] \u003d Timestamp(ts_source).internal"},{"line_number":606,"context_line":""}],"source_content_type":"text/x-python","patch_set":15,"id":"7faddb67_b8a17aab","line":603,"range":{"start_line":603,"start_character":8,"end_line":603,"end_character":59},"updated":"2019-08-21 15:28:07.000000000","message":"is this for s3api? please expand on this comment the intention of this sysmeta as it doesn\u0027t seem to be used anywhere else in this middleware","commit_id":"b2a7005bc7d9ba0610957e73e3f507731b146d2a"},{"author":{"_account_id":9625,"name":"Thiago da Silva","email":"thiagodasilva@gmail.com","username":"thiago"},"change_message_id":"18c55b0494abb3e400e0ba310e03f2bbe3d30739","unresolved":false,"context_lines":[{"line_number":618,"context_line":"        we\u0027ll need to copy it into the versions containers for backwards"},{"line_number":619,"context_line":"        compatibility."},{"line_number":620,"context_line":""},{"line_number":621,"context_line":"        Otherwise, put the client data into the new data from the client into"},{"line_number":622,"context_line":"        the versions container and add a symlink in the versioned container."},{"line_number":623,"context_line":""},{"line_number":624,"context_line":"        :param req: original request."},{"line_number":625,"context_line":"        :param versions_cont: container where previous versions of the object"}],"source_content_type":"text/x-python","patch_set":15,"id":"7faddb67_78aea281","line":622,"range":{"start_line":621,"start_character":8,"end_line":622,"end_character":76},"updated":"2019-08-21 15:28:07.000000000","message":"I think this might need a re-write, how about:\n\n\"If the option `use_symlinks` is True, put the new data from the client into the versions container and add a static symlink in the versioned container.\"","commit_id":"b2a7005bc7d9ba0610957e73e3f507731b146d2a"},{"author":{"_account_id":9625,"name":"Thiago da Silva","email":"thiagodasilva@gmail.com","username":"thiago"},"change_message_id":"7dd41bf9853425e6fef14d9bdd5be5d5484144f3","unresolved":false,"context_lines":[{"line_number":618,"context_line":"        we\u0027ll need to copy it into the versions containers for backwards"},{"line_number":619,"context_line":"        compatibility."},{"line_number":620,"context_line":""},{"line_number":621,"context_line":"        Otherwise, put the client data into the new data from the client into"},{"line_number":622,"context_line":"        the versions container and add a symlink in the versioned container."},{"line_number":623,"context_line":""},{"line_number":624,"context_line":"        :param req: original request."},{"line_number":625,"context_line":"        :param versions_cont: container where previous versions of the object"}],"source_content_type":"text/x-python","patch_set":15,"id":"7faddb67_297f6967","line":622,"range":{"start_line":621,"start_character":8,"end_line":622,"end_character":76},"in_reply_to":"7faddb67_78aea281","updated":"2019-08-22 12:12:29.000000000","message":"Done","commit_id":"b2a7005bc7d9ba0610957e73e3f507731b146d2a"},{"author":{"_account_id":9625,"name":"Thiago da Silva","email":"thiagodasilva@gmail.com","username":"thiago"},"change_message_id":"18c55b0494abb3e400e0ba310e03f2bbe3d30739","unresolved":false,"context_lines":[{"line_number":646,"context_line":"                                            target_etag, put_bytes,"},{"line_number":647,"context_line":"                                            put_content_type)"},{"line_number":648,"context_line":""},{"line_number":649,"context_line":"    def handle_obj_versions_delete_push(self, req, versions_cont, api_version,"},{"line_number":650,"context_line":"                                        account_name, container_name,"},{"line_number":651,"context_line":"                                        object_name):"},{"line_number":652,"context_line":"        \"\"\""}],"source_content_type":"text/x-python","patch_set":15,"id":"7faddb67_b3051bc4","line":649,"range":{"start_line":649,"start_character":8,"end_line":649,"end_character":39},"updated":"2019-08-21 15:28:07.000000000","message":"interesting! no changes needed to handling DELETE when in history mode.\n\nIf use_symlinks\u003dTrue, _copy_current() is a NOOP, so just put down the DELETE marker and clean up the symlink.","commit_id":"b2a7005bc7d9ba0610957e73e3f507731b146d2a"},{"author":{"_account_id":9625,"name":"Thiago da Silva","email":"thiagodasilva@gmail.com","username":"thiago"},"change_message_id":"18c55b0494abb3e400e0ba310e03f2bbe3d30739","unresolved":false,"context_lines":[{"line_number":747,"context_line":"        :param object_name: object name."},{"line_number":748,"context_line":"        \"\"\""},{"line_number":749,"context_line":"        auth_token_header \u003d {\u0027X-Auth-Token\u0027: req.headers.get(\u0027X-Auth-Token\u0027)}"},{"line_number":750,"context_line":"        head_is_tombstone, symlink_target \u003d self._check_head("},{"line_number":751,"context_line":"            req, auth_token_header)"},{"line_number":752,"context_line":""},{"line_number":753,"context_line":"        listing_prefix \u003d self._build_versions_object_prefix(object_name)"}],"source_content_type":"text/x-python","patch_set":15,"id":"7faddb67_d3bf77cd","line":750,"range":{"start_line":750,"start_character":44,"end_line":750,"end_character":60},"updated":"2019-08-21 15:28:07.000000000","message":"we could save a head request, if we do the listing first and realize there are no previous versions, is that possible?","commit_id":"b2a7005bc7d9ba0610957e73e3f507731b146d2a"},{"author":{"_account_id":9625,"name":"Thiago da Silva","email":"thiagodasilva@gmail.com","username":"thiago"},"change_message_id":"18c55b0494abb3e400e0ba310e03f2bbe3d30739","unresolved":false,"context_lines":[{"line_number":791,"context_line":"                        \u0027%s/%s\u0027 % (versions_cont, prev_obj_name)):"},{"line_number":792,"context_line":"                    # if current version is VW symlink and target is"},{"line_number":793,"context_line":"                    # previous_version"},{"line_number":794,"context_line":"                    cleanup_obj_name \u003d prev_obj_name"},{"line_number":795,"context_line":"                    continue"},{"line_number":796,"context_line":"                resp \u003d self._restore_previous_version("},{"line_number":797,"context_line":"                    req, versions_cont, api_version,"}],"source_content_type":"text/x-python","patch_set":15,"id":"7faddb67_53d8677d","line":794,"range":{"start_line":794,"start_character":20,"end_line":794,"end_character":52},"updated":"2019-08-21 15:28:07.000000000","message":"nice, so in the case of symlinks, the steps become:\n1. delete the previous version (top of the queue)\n2. update the symlink to point to the version before that (2nd in queue)\n\nno data movement on a DELETE either!","commit_id":"b2a7005bc7d9ba0610957e73e3f507731b146d2a"},{"author":{"_account_id":9625,"name":"Thiago da Silva","email":"thiagodasilva@gmail.com","username":"thiago"},"change_message_id":"18c55b0494abb3e400e0ba310e03f2bbe3d30739","unresolved":false,"context_lines":[{"line_number":819,"context_line":"            resp \u003d req.get_response(self.app)"},{"line_number":820,"context_line":"        return resp"},{"line_number":821,"context_line":""},{"line_number":822,"context_line":"    def handle_container_request(self, env, start_response):"},{"line_number":823,"context_line":"        app_resp \u003d self._app_call(env)"},{"line_number":824,"context_line":"        if self._response_headers is None:"},{"line_number":825,"context_line":"            self._response_headers \u003d []"}],"source_content_type":"text/x-python","patch_set":15,"id":"7faddb67_6e533817","line":822,"range":{"start_line":822,"start_character":8,"end_line":822,"end_character":32},"updated":"2019-08-21 15:28:07.000000000","message":"this method could use some docstrings.","commit_id":"b2a7005bc7d9ba0610957e73e3f507731b146d2a"},{"author":{"_account_id":9625,"name":"Thiago da Silva","email":"thiagodasilva@gmail.com","username":"thiago"},"change_message_id":"7dd41bf9853425e6fef14d9bdd5be5d5484144f3","unresolved":false,"context_lines":[{"line_number":819,"context_line":"            resp \u003d req.get_response(self.app)"},{"line_number":820,"context_line":"        return resp"},{"line_number":821,"context_line":""},{"line_number":822,"context_line":"    def handle_container_request(self, env, start_response):"},{"line_number":823,"context_line":"        app_resp \u003d self._app_call(env)"},{"line_number":824,"context_line":"        if self._response_headers is None:"},{"line_number":825,"context_line":"            self._response_headers \u003d []"}],"source_content_type":"text/x-python","patch_set":15,"id":"7faddb67_2c0a1720","line":822,"range":{"start_line":822,"start_character":8,"end_line":822,"end_character":32},"in_reply_to":"7faddb67_6e533817","updated":"2019-08-22 12:12:29.000000000","message":"Done","commit_id":"b2a7005bc7d9ba0610957e73e3f507731b146d2a"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"571fcc99eda5828d26575fba392cacf1fb36fc6d","unresolved":false,"context_lines":[{"line_number":259,"context_line":"SYSMETA_VERSIONS_SYMLINK \u003d get_sys_meta_prefix(\u0027object\u0027) + \u0027versions-symlink\u0027"},{"line_number":260,"context_line":""},{"line_number":261,"context_line":""},{"line_number":262,"context_line":"class ByteCountingReader(object):"},{"line_number":263,"context_line":"    \"\"\""},{"line_number":264,"context_line":"    Counts bytes read from file_like so we know how big the object is that"},{"line_number":265,"context_line":"    the client just PUT."}],"source_content_type":"text/x-python","patch_set":16,"id":"7faddb67_b7ef3daf","line":262,"updated":"2019-08-22 18:21:07.000000000","message":"I kinda wonder if this should go in common/utils or something, but I\u0027m content to wait until there\u0027s something else that actually wants it.","commit_id":"cbc9e052491a9dc36f6920489d6bb395d23d5533"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"571fcc99eda5828d26575fba392cacf1fb36fc6d","unresolved":false,"context_lines":[{"line_number":420,"context_line":"        copy_header_subset(source_resp, put_req,"},{"line_number":421,"context_line":"                           lambda k: k.lower() !\u003d \u0027x-timestamp\u0027)"},{"line_number":422,"context_line":"        put_req.environ[\u0027wsgi.input\u0027] \u003d FileLikeIter(source_resp.app_iter)"},{"line_number":423,"context_line":"        slo_size \u003d put_req.headers.get(\u0027X-Object-Sysmeta-Slo-Size\u0027)"},{"line_number":424,"context_line":"        if slo_size:"},{"line_number":425,"context_line":"            put_req.headers[\u0027Content-Type\u0027] +\u003d \u0027; swift_bytes\u003d%s\u0027 % slo_size"},{"line_number":426,"context_line":"            put_req.environ[\u0027swift.content_type_overridden\u0027] \u003d True"}],"source_content_type":"text/x-python","patch_set":16,"id":"7faddb67_772b05ea","line":423,"range":{"start_line":423,"start_character":39,"end_line":423,"end_character":66},"updated":"2019-08-22 18:21:07.000000000","message":"Since we\u0027re already importing from other middlewares -- should we use SYSMETA_SLO_SIZE here?","commit_id":"cbc9e052491a9dc36f6920489d6bb395d23d5533"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"571fcc99eda5828d26575fba392cacf1fb36fc6d","unresolved":false,"context_lines":[{"line_number":546,"context_line":"        close_if_possible(resp.app_iter)"},{"line_number":547,"context_line":"        if is_client_error(resp.status_int):"},{"line_number":548,"context_line":"            # missing container or bad permissions"},{"line_number":549,"context_line":"            if resp.status_int \u003d\u003d 404:"},{"line_number":550,"context_line":"                raise HTTPPreconditionFailed(request\u003dreq)"},{"line_number":551,"context_line":"            raise HTTPException(body\u003dresp.body, status\u003dresp.status,"},{"line_number":552,"context_line":"                                headers\u003dresp.headers)"}],"source_content_type":"text/x-python","patch_set":16,"id":"7faddb67_1768911e","line":549,"range":{"start_line":549,"start_character":34,"end_line":549,"end_character":37},"updated":"2019-08-22 18:21:07.000000000","message":"We\u0027re already importing HTTP_NOT_FOUND, should we just use that?","commit_id":"cbc9e052491a9dc36f6920489d6bb395d23d5533"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"571fcc99eda5828d26575fba392cacf1fb36fc6d","unresolved":false,"context_lines":[{"line_number":600,"context_line":"        vers_obj_name \u003d self._build_versions_object_name("},{"line_number":601,"context_line":"            object_name, ts_source)"},{"line_number":602,"context_line":""},{"line_number":603,"context_line":"        # store internal timestamp as version id to sysmeta"},{"line_number":604,"context_line":"        ver_id_header \u003d get_sys_meta_prefix(\u0027object\u0027) + \u0027version-id\u0027"},{"line_number":605,"context_line":"        get_resp.headers[ver_id_header] \u003d Timestamp(ts_source).internal"},{"line_number":606,"context_line":""}],"source_content_type":"text/x-python","patch_set":16,"id":"7faddb67_370a6d78","line":603,"updated":"2019-08-22 18:21:07.000000000","message":"I think I\u0027m with Thiago -- I\u0027m not sure this is actually needed. Doubly so since the DELETE-as-pop behavior doesn\u0027t require any data movement now.","commit_id":"cbc9e052491a9dc36f6920489d6bb395d23d5533"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"571fcc99eda5828d26575fba392cacf1fb36fc6d","unresolved":false,"context_lines":[{"line_number":635,"context_line":"            return self.app"},{"line_number":636,"context_line":""},{"line_number":637,"context_line":"        req.ensure_x_timestamp()"},{"line_number":638,"context_line":"        put_resp, put_vers_obj_name, put_bytes, put_content_type \u003d \\"},{"line_number":639,"context_line":"            self._put_versioned_obj_from_client(req, versions_cont,"},{"line_number":640,"context_line":"                                                api_version, account_name,"},{"line_number":641,"context_line":"                                                object_name)"}],"source_content_type":"text/x-python","patch_set":16,"id":"7faddb67_d718b9cd","line":638,"range":{"start_line":638,"start_character":8,"end_line":638,"end_character":64},"updated":"2019-08-22 18:21:07.000000000","message":"I\u0027m starting to wonder if we should give the return a little more structure and just pass back a dict...","commit_id":"cbc9e052491a9dc36f6920489d6bb395d23d5533"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"571fcc99eda5828d26575fba392cacf1fb36fc6d","unresolved":false,"context_lines":[{"line_number":748,"context_line":"        \"\"\""},{"line_number":749,"context_line":"        auth_token_header \u003d {\u0027X-Auth-Token\u0027: req.headers.get(\u0027X-Auth-Token\u0027)}"},{"line_number":750,"context_line":"        head_is_tombstone, symlink_target \u003d self._check_head("},{"line_number":751,"context_line":"            req, auth_token_header)"},{"line_number":752,"context_line":""},{"line_number":753,"context_line":"        listing_prefix \u003d self._build_versions_object_prefix(object_name)"},{"line_number":754,"context_line":"        item_iter \u003d self._listing_iter(account_name, versions_cont,"}],"source_content_type":"text/x-python","patch_set":16,"id":"7faddb67_977c81eb","line":751,"updated":"2019-08-22 18:21:07.000000000","message":"OK, so now we *always* do the HEAD, even if there are no old versions?","commit_id":"cbc9e052491a9dc36f6920489d6bb395d23d5533"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"571fcc99eda5828d26575fba392cacf1fb36fc6d","unresolved":false,"context_lines":[{"line_number":759,"context_line":"        resp \u003d None"},{"line_number":760,"context_line":"        for previous_version in item_iter:"},{"line_number":761,"context_line":"            if not authed:"},{"line_number":762,"context_line":"                # validate the write access to the versioned container before"},{"line_number":763,"context_line":"                # making any backend requests"},{"line_number":764,"context_line":"                if \u0027swift.authorize\u0027 in req.environ:"},{"line_number":765,"context_line":"                    container_info \u003d get_container_info("},{"line_number":766,"context_line":"                        req.environ, self.app)"}],"source_content_type":"text/x-python","patch_set":16,"id":"7faddb67_d76d192f","line":763,"range":{"start_line":762,"start_character":18,"end_line":763,"end_character":45},"updated":"2019-08-22 18:21:07.000000000","message":"...which means this no longer holds. But its just a read, right? Should be fine...","commit_id":"cbc9e052491a9dc36f6920489d6bb395d23d5533"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"cdd9e9260f8230a2d1616eeb8d54207fb1f154fa","unresolved":false,"context_lines":[{"line_number":845,"context_line":"                except ValueError:"},{"line_number":846,"context_line":"                    app_resp \u003d [body]"},{"line_number":847,"context_line":"                else:"},{"line_number":848,"context_line":"                    for item in listing:"},{"line_number":849,"context_line":"                        if not all(x in item for x in ("},{"line_number":850,"context_line":"                                \u0027symlink_path\u0027,"},{"line_number":851,"context_line":"                                \u0027symlink_etag\u0027,"}],"source_content_type":"text/x-python","patch_set":16,"id":"7faddb67_5fe9457c","line":848,"updated":"2019-08-21 20:45:52.000000000","message":"At some point I really need to invest some time into making these sorts of listing manipulations suck less :-/","commit_id":"cbc9e052491a9dc36f6920489d6bb395d23d5533"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"cdd9e9260f8230a2d1616eeb8d54207fb1f154fa","unresolved":false,"context_lines":[{"line_number":1075,"context_line":"                    return self.maybe_redirect_post("},{"line_number":1076,"context_line":"                        req, api_version, account, container, obj,"},{"line_number":1077,"context_line":"                        allow_versioned_writes)(env, start_response)"},{"line_number":1078,"context_line":"                except HTTPException as error_response:"},{"line_number":1079,"context_line":"                    return error_response(env, start_response)"},{"line_number":1080,"context_line":"        return self.app(env, start_response)"},{"line_number":1081,"context_line":""}],"source_content_type":"text/x-python","patch_set":16,"id":"7faddb67_59e645b2","line":1078,"range":{"start_line":1078,"start_character":16,"end_line":1078,"end_character":54},"updated":"2019-08-21 20:45:52.000000000","message":"I don\u0027t think anything in maybe_redirect_post() would trip this...\n\nPretty sure that was just a left-over from me cribbing the PUT/DELETE logic.","commit_id":"cbc9e052491a9dc36f6920489d6bb395d23d5533"},{"author":{"_account_id":9625,"name":"Thiago da Silva","email":"thiagodasilva@gmail.com","username":"thiago"},"change_message_id":"7dd41bf9853425e6fef14d9bdd5be5d5484144f3","unresolved":false,"context_lines":[{"line_number":1075,"context_line":"                    return self.maybe_redirect_post("},{"line_number":1076,"context_line":"                        req, api_version, account, container, obj,"},{"line_number":1077,"context_line":"                        allow_versioned_writes)(env, start_response)"},{"line_number":1078,"context_line":"                except HTTPException as error_response:"},{"line_number":1079,"context_line":"                    return error_response(env, start_response)"},{"line_number":1080,"context_line":"        return self.app(env, start_response)"},{"line_number":1081,"context_line":""}],"source_content_type":"text/x-python","patch_set":16,"id":"7faddb67_2ca0d742","line":1078,"range":{"start_line":1078,"start_character":16,"end_line":1078,"end_character":54},"in_reply_to":"7faddb67_59e645b2","updated":"2019-08-22 12:12:29.000000000","message":"Done","commit_id":"cbc9e052491a9dc36f6920489d6bb395d23d5533"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"cdd9e9260f8230a2d1616eeb8d54207fb1f154fa","unresolved":false,"context_lines":[{"line_number":1090,"context_line":"    if config_true_value(conf.get(\u0027allow_versioned_writes\u0027)):"},{"line_number":1091,"context_line":"        if \u0027use_symlinks\u0027 in conf:"},{"line_number":1092,"context_line":"            use_symlinks \u003d config_true_value(conf[\u0027use_symlinks\u0027])"},{"line_number":1093,"context_line":"        if use_symlinks and \u0027symlink\u0027 not in get_swift_info():"},{"line_number":1094,"context_line":"            logger.warning(\u0027symlink middleware is not enabled! Disabling \u0027"},{"line_number":1095,"context_line":"                           \u0027use_symlink in versioned_writes.\u0027)"},{"line_number":1096,"context_line":"            use_symlinks \u003d False"},{"line_number":1097,"context_line":""},{"line_number":1098,"context_line":"        register_swift_info("},{"line_number":1099,"context_line":"            \u0027versioned_writes\u0027,"}],"source_content_type":"text/x-python","patch_set":16,"id":"7faddb67_795b0185","line":1096,"range":{"start_line":1093,"start_character":8,"end_line":1096,"end_character":32},"updated":"2019-08-21 20:45:52.000000000","message":"Nice.\n\nWould it be better for us to go ahead and raise an error, though? Operator said they wanted something and we aren\u0027t going to do it... it\u0027s not like we default it to on. I kinda feel like refusing to start is justified.","commit_id":"cbc9e052491a9dc36f6920489d6bb395d23d5533"},{"author":{"_account_id":9625,"name":"Thiago da Silva","email":"thiagodasilva@gmail.com","username":"thiago"},"change_message_id":"7dd41bf9853425e6fef14d9bdd5be5d5484144f3","unresolved":false,"context_lines":[{"line_number":1090,"context_line":"    if config_true_value(conf.get(\u0027allow_versioned_writes\u0027)):"},{"line_number":1091,"context_line":"        if \u0027use_symlinks\u0027 in conf:"},{"line_number":1092,"context_line":"            use_symlinks \u003d config_true_value(conf[\u0027use_symlinks\u0027])"},{"line_number":1093,"context_line":"        if use_symlinks and \u0027symlink\u0027 not in get_swift_info():"},{"line_number":1094,"context_line":"            logger.warning(\u0027symlink middleware is not enabled! Disabling \u0027"},{"line_number":1095,"context_line":"                           \u0027use_symlink in versioned_writes.\u0027)"},{"line_number":1096,"context_line":"            use_symlinks \u003d False"},{"line_number":1097,"context_line":""},{"line_number":1098,"context_line":"        register_swift_info("},{"line_number":1099,"context_line":"            \u0027versioned_writes\u0027,"}],"source_content_type":"text/x-python","patch_set":16,"id":"7faddb67_6c7a4ff1","line":1096,"range":{"start_line":1093,"start_character":8,"end_line":1096,"end_character":32},"in_reply_to":"7faddb67_795b0185","updated":"2019-08-22 12:12:29.000000000","message":"I\u0027m trying to remember where else in the code we have similar situation. any pointers to what\u0027s been our procedure in the past?","commit_id":"cbc9e052491a9dc36f6920489d6bb395d23d5533"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"571fcc99eda5828d26575fba392cacf1fb36fc6d","unresolved":false,"context_lines":[{"line_number":423,"context_line":"        slo_size \u003d put_req.headers.get(\u0027X-Object-Sysmeta-Slo-Size\u0027)"},{"line_number":424,"context_line":"        if slo_size:"},{"line_number":425,"context_line":"            put_req.headers[\u0027Content-Type\u0027] +\u003d \u0027; swift_bytes\u003d%s\u0027 % slo_size"},{"line_number":426,"context_line":"            put_req.environ[\u0027swift.content_type_overridden\u0027] \u003d True"},{"line_number":427,"context_line":"        put_resp \u003d put_req.get_response(self.app)"},{"line_number":428,"context_line":"        close_if_possible(source_resp.app_iter)"},{"line_number":429,"context_line":"        return put_resp"}],"source_content_type":"text/x-python","patch_set":18,"id":"7faddb67_a6f93b4f","line":426,"updated":"2019-08-22 18:21:07.000000000","message":"Solid fix!\n\nIf we *really* wanted, we could even look for X-Static-Large-Object, slurp the whole thing into memory if we find it, and add size/etag sysmeta for pre-2.12.0 SLOs... but that\u0027s *way* more than VW should be aware of.","commit_id":"6081dca15047588197288dae5dceaf2d77113000"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"571fcc99eda5828d26575fba392cacf1fb36fc6d","unresolved":false,"context_lines":[{"line_number":442,"context_line":"        # move the client request body over"},{"line_number":443,"context_line":"        # note that the WSGI environ may be *further* manipulated; hold on to"},{"line_number":444,"context_line":"        # a reference to the byte counter so we can get the bytes_read"},{"line_number":445,"context_line":"        if req.content_length is None:"},{"line_number":446,"context_line":"            put_req.headers[\u0027transfer-encoding\u0027] \u003d \\"},{"line_number":447,"context_line":"                req.headers.get(\u0027transfer-encoding\u0027)"},{"line_number":448,"context_line":"        else:"}],"source_content_type":"text/x-python","patch_set":18,"id":"7faddb67_c68b17be","line":445,"range":{"start_line":445,"start_character":15,"end_line":445,"end_character":29},"updated":"2019-08-22 18:21:07.000000000","message":"Better to use req.message_length() -- RFC demands that we trust transfer-encoding over content-length.","commit_id":"6081dca15047588197288dae5dceaf2d77113000"},{"author":{"_account_id":9625,"name":"Thiago da Silva","email":"thiagodasilva@gmail.com","username":"thiago"},"change_message_id":"dd73c8a44268244991b7a3212c73bf1b6c28a782","unresolved":false,"context_lines":[{"line_number":442,"context_line":"        # move the client request body over"},{"line_number":443,"context_line":"        # note that the WSGI environ may be *further* manipulated; hold on to"},{"line_number":444,"context_line":"        # a reference to the byte counter so we can get the bytes_read"},{"line_number":445,"context_line":"        if req.content_length is None:"},{"line_number":446,"context_line":"            put_req.headers[\u0027transfer-encoding\u0027] \u003d \\"},{"line_number":447,"context_line":"                req.headers.get(\u0027transfer-encoding\u0027)"},{"line_number":448,"context_line":"        else:"}],"source_content_type":"text/x-python","patch_set":18,"id":"7faddb67_5e2124fc","line":445,"range":{"start_line":445,"start_character":15,"end_line":445,"end_character":29},"in_reply_to":"7faddb67_c68b17be","updated":"2019-08-26 18:45:09.000000000","message":"Done","commit_id":"6081dca15047588197288dae5dceaf2d77113000"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"571fcc99eda5828d26575fba392cacf1fb36fc6d","unresolved":false,"context_lines":[{"line_number":454,"context_line":"        for header, value in req.headers.items():"},{"line_number":455,"context_line":"            if header.lower() in (\u0027x-static-large-object\u0027, \u0027content-type\u0027,"},{"line_number":456,"context_line":"                                  \u0027x-symlink-target\u0027,"},{"line_number":457,"context_line":"                                  \u0027x-object-manifest\u0027, \u0027etag\u0027) or \\"},{"line_number":458,"context_line":"                    is_sys_or_user_meta(\u0027object\u0027, header) or \\"},{"line_number":459,"context_line":"                    is_object_transient_sysmeta(header):"},{"line_number":460,"context_line":"                put_req.headers[header] \u003d value"}],"source_content_type":"text/x-python","patch_set":18,"id":"7faddb67_41539117","line":457,"updated":"2019-08-22 18:21:07.000000000","message":"What about content-disposition, content-encoding, etc.? x-symlink-target-account, x-symlink-target-etag?\n\nWhat about non-default allowed_headers configured on the object server? Should we just move *everything* over?\n\nWell... *maybe* not X-Delete-At/X-Delete-After? What *should* we do about those?","commit_id":"6081dca15047588197288dae5dceaf2d77113000"},{"author":{"_account_id":9625,"name":"Thiago da Silva","email":"thiagodasilva@gmail.com","username":"thiago"},"change_message_id":"dd73c8a44268244991b7a3212c73bf1b6c28a782","unresolved":false,"context_lines":[{"line_number":454,"context_line":"        for header, value in req.headers.items():"},{"line_number":455,"context_line":"            if header.lower() in (\u0027x-static-large-object\u0027, \u0027content-type\u0027,"},{"line_number":456,"context_line":"                                  \u0027x-symlink-target\u0027,"},{"line_number":457,"context_line":"                                  \u0027x-object-manifest\u0027, \u0027etag\u0027) or \\"},{"line_number":458,"context_line":"                    is_sys_or_user_meta(\u0027object\u0027, header) or \\"},{"line_number":459,"context_line":"                    is_object_transient_sysmeta(header):"},{"line_number":460,"context_line":"                put_req.headers[header] \u003d value"}],"source_content_type":"text/x-python","patch_set":18,"id":"7faddb67_947f7b65","line":457,"in_reply_to":"7faddb67_41539117","updated":"2019-08-26 18:45:09.000000000","message":"yeah, we probably should consider moving everything because of allowed_headers options[1]. Then we can just let object-server handle the headers. maybe do something like [2]. thoughts?\n\n[1] - https://github.com/openstack/swift/blob/2.22.0/etc/object-server.conf-sample#L135\n[2] - https://github.com/openstack/swift/blob/2.22.0/swift/common/middleware/copy.py#L368,L372","commit_id":"6081dca15047588197288dae5dceaf2d77113000"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"571fcc99eda5828d26575fba392cacf1fb36fc6d","unresolved":false,"context_lines":[{"line_number":463,"context_line":"                req.environ.pop(\u0027swift.content_type_overridden\u0027)"},{"line_number":464,"context_line":""},{"line_number":465,"context_line":"        # do the write"},{"line_number":466,"context_line":"        put_req.headers[\u0027x-timestamp\u0027] \u003d req.timestamp.internal"},{"line_number":467,"context_line":"        put_resp \u003d put_req.get_response(self.app)"},{"line_number":468,"context_line":"        self._check_response_error(req, put_resp)"},{"line_number":469,"context_line":"        with closing_if_possible(put_resp.app_iter), closing_if_possible("}],"source_content_type":"text/x-python","patch_set":18,"id":"7faddb67_61100d02","line":466,"updated":"2019-08-22 18:21:07.000000000","message":"Do we really have to round-trip through https://github.com/openstack/swift/blob/2.22.0/swift/common/swob.py#L1014-L1028 instead of copying the header directly?","commit_id":"6081dca15047588197288dae5dceaf2d77113000"},{"author":{"_account_id":9625,"name":"Thiago da Silva","email":"thiagodasilva@gmail.com","username":"thiago"},"change_message_id":"dd73c8a44268244991b7a3212c73bf1b6c28a782","unresolved":false,"context_lines":[{"line_number":463,"context_line":"                req.environ.pop(\u0027swift.content_type_overridden\u0027)"},{"line_number":464,"context_line":""},{"line_number":465,"context_line":"        # do the write"},{"line_number":466,"context_line":"        put_req.headers[\u0027x-timestamp\u0027] \u003d req.timestamp.internal"},{"line_number":467,"context_line":"        put_resp \u003d put_req.get_response(self.app)"},{"line_number":468,"context_line":"        self._check_response_error(req, put_resp)"},{"line_number":469,"context_line":"        with closing_if_possible(put_resp.app_iter), closing_if_possible("}],"source_content_type":"text/x-python","patch_set":18,"id":"7faddb67_0e17d656","line":466,"in_reply_to":"7faddb67_61100d02","updated":"2019-08-26 18:45:09.000000000","message":"done","commit_id":"6081dca15047588197288dae5dceaf2d77113000"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"571fcc99eda5828d26575fba392cacf1fb36fc6d","unresolved":false,"context_lines":[{"line_number":476,"context_line":"        slo_size \u003d put_req.headers.get(\u0027X-Object-Sysmeta-Slo-Size\u0027)"},{"line_number":477,"context_line":"        if slo_size:"},{"line_number":478,"context_line":"            put_bytes \u003d slo_size"},{"line_number":479,"context_line":"        put_content_type \u003d parse_content_type("},{"line_number":480,"context_line":"            put_req.headers[\u0027Content-Type\u0027])[0]"},{"line_number":481,"context_line":""},{"line_number":482,"context_line":"        return (put_resp, vers_obj_name, put_bytes, put_content_type)"},{"line_number":483,"context_line":""}],"source_content_type":"text/x-python","patch_set":18,"id":"7faddb67_41315159","line":480,"range":{"start_line":479,"start_character":8,"end_line":480,"end_character":47},"updated":"2019-08-22 18:21:07.000000000","message":"Do we have to do this here? We copied it from req\u0027s content-type, yeah? Can _put_symlink_to_version() just have\n\n req.headers[\u0027Content-Type\u0027] \u003d parse_content_type(\n     req.headers[\u0027Content-Type\u0027])[0]\n\n?","commit_id":"6081dca15047588197288dae5dceaf2d77113000"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"571fcc99eda5828d26575fba392cacf1fb36fc6d","unresolved":false,"context_lines":[{"line_number":493,"context_line":"            if \u0027slo_etag\u0027 in params:"},{"line_number":494,"context_line":"                # N.B. container-server put slo-size (swift_bytes) in bytes"},{"line_number":495,"context_line":"                req.headers[get_container_update_override_key(\u0027etag\u0027)] \u003d \\"},{"line_number":496,"context_line":"                    \u0027%s; slo_etag\u003d%s\u0027 % (target_etag, params[\u0027slo_etag\u0027])"},{"line_number":497,"context_line":"            resp \u003d self._put_symlink_to_version("},{"line_number":498,"context_line":"                req, versions_cont, prev_obj_name, api_version,"},{"line_number":499,"context_line":"                account_name, object_name, target_etag,"}],"source_content_type":"text/x-python","patch_set":18,"id":"7faddb67_e16f1d26","line":496,"range":{"start_line":496,"start_character":41,"end_line":496,"end_character":52},"updated":"2019-08-22 18:21:07.000000000","message":"No other params? What about s3_etag?","commit_id":"6081dca15047588197288dae5dceaf2d77113000"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"2ec059fd81f2fc3e63a390c82e856905bbd284d6","unresolved":false,"context_lines":[{"line_number":498,"context_line":"                req, versions_cont, prev_obj_name, api_version,"},{"line_number":499,"context_line":"                account_name, object_name, target_etag,"},{"line_number":500,"context_line":"                put_bytes, put_content_type)"},{"line_number":501,"context_line":"            self._check_response_error(req, resp)"},{"line_number":502,"context_line":"            close_if_possible(resp.app_iter)"},{"line_number":503,"context_line":"        else:"},{"line_number":504,"context_line":"            self._restore_data(req, versions_cont, api_version, account_name,"}],"source_content_type":"text/x-python","patch_set":18,"id":"7faddb67_5284c1d3","line":501,"updated":"2019-08-22 22:44:21.000000000","message":"Hmm. So we don\u0027t actually verify that the target still exists -- we\u0027re entirely reliant on listings being \"good\"....","commit_id":"6081dca15047588197288dae5dceaf2d77113000"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"2ec059fd81f2fc3e63a390c82e856905bbd284d6","unresolved":false,"context_lines":[{"line_number":503,"context_line":"        else:"},{"line_number":504,"context_line":"            self._restore_data(req, versions_cont, api_version, account_name,"},{"line_number":505,"context_line":"                               container_name, object_name, prev_obj_name)"},{"line_number":506,"context_line":"        return HTTPNoContent(request\u003dreq)"},{"line_number":507,"context_line":""},{"line_number":508,"context_line":"    def _put_symlink_to_version(self, req, versions_cont, put_vers_obj_name,"},{"line_number":509,"context_line":"                                api_version, account_name, object_name,"}],"source_content_type":"text/x-python","patch_set":18,"id":"7faddb67_34c5723e","line":506,"updated":"2019-08-22 22:44:21.000000000","message":"Huh. So there\u0027s just the one return? And it\u0027s always that 204.\n\nAlso, I think we lost some of the nuance of _restore_data() -- in particular, if we\u0027re not using symlinks and the version we\u0027re trying to restore doesn\u0027t actually exist, _restore_data() would return False indicating that we should keep walking the listing looking for something that *does* exist.","commit_id":"6081dca15047588197288dae5dceaf2d77113000"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"571fcc99eda5828d26575fba392cacf1fb36fc6d","unresolved":false,"context_lines":[{"line_number":511,"context_line":""},{"line_number":512,"context_line":"        req.method \u003d \u0027PUT\u0027"},{"line_number":513,"context_line":"        # inch x-timestamp forward, just in case"},{"line_number":514,"context_line":"        req.ensure_x_timestamp()"},{"line_number":515,"context_line":"        req.headers[\u0027X-Timestamp\u0027] \u003d Timestamp("},{"line_number":516,"context_line":"            req.timestamp, offset\u003d1).internal"},{"line_number":517,"context_line":"        req.headers[TGT_ETAG_SYSMETA_SYMLINK_HDR] \u003d put_etag"}],"source_content_type":"text/x-python","patch_set":18,"id":"7faddb67_21c9b578","line":514,"updated":"2019-08-22 18:21:07.000000000","message":"This was already done in handle_obj_versions_put), yeah?","commit_id":"6081dca15047588197288dae5dceaf2d77113000"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"571fcc99eda5828d26575fba392cacf1fb36fc6d","unresolved":false,"context_lines":[{"line_number":516,"context_line":"            req.timestamp, offset\u003d1).internal"},{"line_number":517,"context_line":"        req.headers[TGT_ETAG_SYSMETA_SYMLINK_HDR] \u003d put_etag"},{"line_number":518,"context_line":"        req.headers[TGT_BYTES_SYSMETA_SYMLINK_HDR] \u003d put_bytes"},{"line_number":519,"context_line":"        # N.B. in stack mode DELETE we use content_type from listing"},{"line_number":520,"context_line":"        req.headers[\u0027Content-Type\u0027] \u003d put_content_type"},{"line_number":521,"context_line":"        req.headers[TGT_OBJ_SYMLINK_HDR] \u003d wsgi_quote(\u0027%s/%s\u0027 % ("},{"line_number":522,"context_line":"            versions_cont, put_vers_obj_name))"}],"source_content_type":"text/x-python","patch_set":18,"id":"7faddb67_01c83954","line":519,"updated":"2019-08-22 18:21:07.000000000","message":"Well there\u0027s an interesting thought... we follow 307s on POST to get updated content-types on the backing objects, but the listing may lag...\n\nI think it\u0027s probably OK, though? Like, you\u0027d need to do a POST then (within some smallish window) an overwrite and a DELETE to be affected... and I don\u0027t have any better solution, anyway. Particularly when you consider how a proxy could fall over for no good reason between landing the POST on the VW symlink and following the 307 to POST to the backing object.","commit_id":"6081dca15047588197288dae5dceaf2d77113000"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"571fcc99eda5828d26575fba392cacf1fb36fc6d","unresolved":false,"context_lines":[{"line_number":523,"context_line":"        req.headers[SYSMETA_VERSIONS_SYMLINK] \u003d \u0027true\u0027"},{"line_number":524,"context_line":"        req.headers[SYMLOOP_EXTEND] \u003d \u0027true\u0027"},{"line_number":525,"context_line":"        not_for_symlink_headers \u003d ("},{"line_number":526,"context_line":"            \u0027ETag\u0027, TGT_ACCT_SYMLINK_HDR, \u0027X-If-Delete-At\u0027,"},{"line_number":527,"context_line":"            \u0027X-Object-Manifest\u0027, \u0027X-Static-Large-Object\u0027,"},{"line_number":528,"context_line":"            \u0027X-Object-Sysmeta-Slo-Etag\u0027, \u0027X-Object-Sysmeta-Slo-Size\u0027,"},{"line_number":529,"context_line":"        )"}],"source_content_type":"text/x-python","patch_set":18,"id":"7faddb67_a115a59d","line":526,"range":{"start_line":526,"start_character":42,"end_line":526,"end_character":58},"updated":"2019-08-22 18:21:07.000000000","message":"I\u0027m not sure what this has to do with PUTs -- I thought it was a DELETE header?","commit_id":"6081dca15047588197288dae5dceaf2d77113000"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"2ec059fd81f2fc3e63a390c82e856905bbd284d6","unresolved":false,"context_lines":[{"line_number":726,"context_line":"            # if there\u0027s any other kind of error with a broken link..."},{"line_number":727,"context_line":"            # I guess give up?"},{"line_number":728,"context_line":"            self._check_response_error(req, hresp)"},{"line_number":729,"context_line":"            if hresp.headers.get(SYSMETA_VERSIONS_SYMLINK) \u003d\u003d \u0027true\u0027:"},{"line_number":730,"context_line":"                symlink_target \u003d hresp.headers.get(TGT_OBJ_SYMLINK_HDR)"},{"line_number":731,"context_line":"        close_if_possible(hresp.app_iter)"},{"line_number":732,"context_line":"        return head_is_tombstone, symlink_target"}],"source_content_type":"text/x-python","patch_set":18,"id":"7faddb67_5456eed0","line":729,"updated":"2019-08-22 22:44:21.000000000","message":"I wonder if there should be a check that the target actually is in the (current) archive container... you might switch between archive containers or something...","commit_id":"6081dca15047588197288dae5dceaf2d77113000"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"2ec059fd81f2fc3e63a390c82e856905bbd284d6","unresolved":false,"context_lines":[{"line_number":777,"context_line":"                    # is also a DELETE, we need only to roll back the top of"},{"line_number":778,"context_line":"                    # the queue by clearing one marker"},{"line_number":779,"context_line":"                    cleanup_obj_name \u003d bytes_to_wsgi("},{"line_number":780,"context_line":"                        previous_version[\u0027name\u0027].encode(\u0027utf-8\u0027))"},{"line_number":781,"context_line":"                else:"},{"line_number":782,"context_line":"                    # the current version is something in the root container,"},{"line_number":783,"context_line":"                    # and the previous version was this DELETE marker, we need"}],"source_content_type":"text/x-python","patch_set":18,"id":"7faddb67_d49ade6d","line":780,"updated":"2019-08-22 22:44:21.000000000","message":"Wait, where\u0027s the restore? I see us clean up the marker, but I was expecting another loop to look for a version_to_restore, then (assuming it\u0027s not another delete marker) a call to _restore_previous_version()...","commit_id":"6081dca15047588197288dae5dceaf2d77113000"},{"author":{"_account_id":9625,"name":"Thiago da Silva","email":"thiagodasilva@gmail.com","username":"thiago"},"change_message_id":"dd73c8a44268244991b7a3212c73bf1b6c28a782","unresolved":false,"context_lines":[{"line_number":777,"context_line":"                    # is also a DELETE, we need only to roll back the top of"},{"line_number":778,"context_line":"                    # the queue by clearing one marker"},{"line_number":779,"context_line":"                    cleanup_obj_name \u003d bytes_to_wsgi("},{"line_number":780,"context_line":"                        previous_version[\u0027name\u0027].encode(\u0027utf-8\u0027))"},{"line_number":781,"context_line":"                else:"},{"line_number":782,"context_line":"                    # the current version is something in the root container,"},{"line_number":783,"context_line":"                    # and the previous version was this DELETE marker, we need"}],"source_content_type":"text/x-python","patch_set":18,"id":"7faddb67_a2d9f984","line":780,"in_reply_to":"7faddb67_d49ade6d","updated":"2019-08-26 18:45:09.000000000","message":"Done","commit_id":"6081dca15047588197288dae5dceaf2d77113000"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"2ec059fd81f2fc3e63a390c82e856905bbd284d6","unresolved":false,"context_lines":[{"line_number":783,"context_line":"                    # and the previous version was this DELETE marker, we need"},{"line_number":784,"context_line":"                    # to clear the top of the queue so this marker becomes the"},{"line_number":785,"context_line":"                    # most recent reference"},{"line_number":786,"context_line":"                    resp \u003d req.get_response(self.app)"},{"line_number":787,"context_line":"                break"},{"line_number":788,"context_line":"            else:"},{"line_number":789,"context_line":"                prev_obj_name \u003d bytes_to_wsgi("}],"source_content_type":"text/x-python","patch_set":18,"id":"7faddb67_52a60112","line":786,"updated":"2019-08-22 22:44:21.000000000","message":"We don\u0027t set\n\n cleanup_obj_name \u003d symlink_target\n\nor something? I suppose the expectation is that it\u0027d 404... but maybe listings are out of date?","commit_id":"6081dca15047588197288dae5dceaf2d77113000"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"2ec059fd81f2fc3e63a390c82e856905bbd284d6","unresolved":false,"context_lines":[{"line_number":804,"context_line":"        else:"},{"line_number":805,"context_line":"            # didn\u0027t find a previous version to break out go ahead and do the"},{"line_number":806,"context_line":"            # DELETE to the target, it\u0027s the last version"},{"line_number":807,"context_line":"            resp \u003d req.get_response(self.app)"},{"line_number":808,"context_line":""},{"line_number":809,"context_line":"        # we found something in the queue we want to clean-up"},{"line_number":810,"context_line":"        if cleanup_obj_name:"}],"source_content_type":"text/x-python","patch_set":18,"id":"7faddb67_12c5e93d","line":807,"updated":"2019-08-22 22:44:21.000000000","message":"Along the same lines as above, we should probably try to clean up symlink_target here.","commit_id":"6081dca15047588197288dae5dceaf2d77113000"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"2ec059fd81f2fc3e63a390c82e856905bbd284d6","unresolved":false,"context_lines":[{"line_number":806,"context_line":"            # DELETE to the target, it\u0027s the last version"},{"line_number":807,"context_line":"            resp \u003d req.get_response(self.app)"},{"line_number":808,"context_line":""},{"line_number":809,"context_line":"        # we found something in the queue we want to clean-up"},{"line_number":810,"context_line":"        if cleanup_obj_name:"},{"line_number":811,"context_line":"            if resp:"},{"line_number":812,"context_line":"                close_if_possible(resp.app_iter)"}],"source_content_type":"text/x-python","patch_set":18,"id":"7faddb67_32aee581","line":809,"range":{"start_line":809,"start_character":42,"end_line":809,"end_character":61},"updated":"2019-08-22 22:44:21.000000000","message":"\u003e we want to try to clean-up\n\nFTFY -- it\u0027s not like we actually look at the return code or anything ;-)","commit_id":"6081dca15047588197288dae5dceaf2d77113000"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"30b5b00065da6106bc49416f6a7f5f21cfc442d0","unresolved":false,"context_lines":[{"line_number":1030,"context_line":"                            allow_versioned_writes):"},{"line_number":1031,"context_line":"        resp \u003d req.get_response(self.app)"},{"line_number":1032,"context_line":"        if resp.status_int \u003d\u003d 307 and resp.headers.get("},{"line_number":1033,"context_line":"                SYSMETA_VERSIONS_SYMLINK, \u0027false\u0027) \u003d\u003d \u0027true\u0027:"},{"line_number":1034,"context_line":"            req.path_info \u003d wsgi_unquote(resp.headers[\u0027Location\u0027])"},{"line_number":1035,"context_line":"            req.environ[\u0027swift.source\u0027] \u003d \u0027VW\u0027"},{"line_number":1036,"context_line":"            # we\u0027ve changed the path and don\u0027t want any override going on"}],"source_content_type":"text/x-python","patch_set":18,"id":"7faddb67_04fcae0a","line":1033,"range":{"start_line":1033,"start_character":51,"end_line":1033,"end_character":60},"updated":"2019-08-23 23:19:19.000000000","message":"Again, config_true_value() might be nice.","commit_id":"6081dca15047588197288dae5dceaf2d77113000"},{"author":{"_account_id":9625,"name":"Thiago da Silva","email":"thiagodasilva@gmail.com","username":"thiago"},"change_message_id":"dd73c8a44268244991b7a3212c73bf1b6c28a782","unresolved":false,"context_lines":[{"line_number":1030,"context_line":"                            allow_versioned_writes):"},{"line_number":1031,"context_line":"        resp \u003d req.get_response(self.app)"},{"line_number":1032,"context_line":"        if resp.status_int \u003d\u003d 307 and resp.headers.get("},{"line_number":1033,"context_line":"                SYSMETA_VERSIONS_SYMLINK, \u0027false\u0027) \u003d\u003d \u0027true\u0027:"},{"line_number":1034,"context_line":"            req.path_info \u003d wsgi_unquote(resp.headers[\u0027Location\u0027])"},{"line_number":1035,"context_line":"            req.environ[\u0027swift.source\u0027] \u003d \u0027VW\u0027"},{"line_number":1036,"context_line":"            # we\u0027ve changed the path and don\u0027t want any override going on"}],"source_content_type":"text/x-python","patch_set":18,"id":"7faddb67_921bf2c8","line":1033,"range":{"start_line":1033,"start_character":51,"end_line":1033,"end_character":60},"in_reply_to":"7faddb67_04fcae0a","updated":"2019-08-26 18:45:09.000000000","message":"Done","commit_id":"6081dca15047588197288dae5dceaf2d77113000"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"571fcc99eda5828d26575fba392cacf1fb36fc6d","unresolved":false,"context_lines":[{"line_number":1035,"context_line":"            req.environ[\u0027swift.source\u0027] \u003d \u0027VW\u0027"},{"line_number":1036,"context_line":"            # we\u0027ve changed the path and don\u0027t want any override going on"},{"line_number":1037,"context_line":"            req.environ.pop(\u0027HTTP_X_BACKEND_STORAGE_POLICY_INDEX\u0027, None)"},{"line_number":1038,"context_line":"            resp \u003d req.get_response(self.app)"},{"line_number":1039,"context_line":"        return resp"},{"line_number":1040,"context_line":""},{"line_number":1041,"context_line":"    def __call__(self, env, start_response):"}],"source_content_type":"text/x-python","patch_set":18,"id":"7faddb67_01c27987","line":1038,"updated":"2019-08-22 18:21:07.000000000","message":":-/\n\nSo, not pre-authed? POST gets different perms than PUT?\n\nSeparately, open question: should we forward expiry headers?","commit_id":"6081dca15047588197288dae5dceaf2d77113000"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"30b5b00065da6106bc49416f6a7f5f21cfc442d0","unresolved":false,"context_lines":[{"line_number":1035,"context_line":"            req.environ[\u0027swift.source\u0027] \u003d \u0027VW\u0027"},{"line_number":1036,"context_line":"            # we\u0027ve changed the path and don\u0027t want any override going on"},{"line_number":1037,"context_line":"            req.environ.pop(\u0027HTTP_X_BACKEND_STORAGE_POLICY_INDEX\u0027, None)"},{"line_number":1038,"context_line":"            resp \u003d req.get_response(self.app)"},{"line_number":1039,"context_line":"        return resp"},{"line_number":1040,"context_line":""},{"line_number":1041,"context_line":"    def __call__(self, env, start_response):"}],"source_content_type":"text/x-python","patch_set":18,"id":"7faddb67_59013306","line":1038,"in_reply_to":"7faddb67_01c27987","updated":"2019-08-23 23:19:19.000000000","message":"Oh, but we added the assertion at https://review.opendev.org/#/c/633857/18/test/functional/test_versioned_writes.py@659 -- I guess I\u0027m just confused? How was that authorized??","commit_id":"6081dca15047588197288dae5dceaf2d77113000"},{"author":{"_account_id":9625,"name":"Thiago da Silva","email":"thiagodasilva@gmail.com","username":"thiago"},"change_message_id":"dd73c8a44268244991b7a3212c73bf1b6c28a782","unresolved":false,"context_lines":[{"line_number":1035,"context_line":"            req.environ[\u0027swift.source\u0027] \u003d \u0027VW\u0027"},{"line_number":1036,"context_line":"            # we\u0027ve changed the path and don\u0027t want any override going on"},{"line_number":1037,"context_line":"            req.environ.pop(\u0027HTTP_X_BACKEND_STORAGE_POLICY_INDEX\u0027, None)"},{"line_number":1038,"context_line":"            resp \u003d req.get_response(self.app)"},{"line_number":1039,"context_line":"        return resp"},{"line_number":1040,"context_line":""},{"line_number":1041,"context_line":"    def __call__(self, env, start_response):"}],"source_content_type":"text/x-python","patch_set":18,"id":"7faddb67_4afdda39","line":1038,"in_reply_to":"7faddb67_01c27987","updated":"2019-08-26 18:45:09.000000000","message":"interesting that we have a ACLs post test where user2 should be able to post to \u0027source\u0027 container but not to versions container. what am i missing?","commit_id":"6081dca15047588197288dae5dceaf2d77113000"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"571fcc99eda5828d26575fba392cacf1fb36fc6d","unresolved":false,"context_lines":[{"line_number":1093,"context_line":""},{"line_number":1094,"context_line":"    use_symlinks \u003d False"},{"line_number":1095,"context_line":"    if config_true_value(conf.get(\u0027allow_versioned_writes\u0027)):"},{"line_number":1096,"context_line":"        if \u0027use_symlinks\u0027 in conf:"},{"line_number":1097,"context_line":"            use_symlinks \u003d config_true_value(conf[\u0027use_symlinks\u0027])"},{"line_number":1098,"context_line":"        if use_symlinks and \u0027symlink\u0027 not in get_swift_info():"},{"line_number":1099,"context_line":"            logger.warning(\u0027symlink middleware is not enabled! Disabling \u0027"},{"line_number":1100,"context_line":"                           \u0027use_symlink in versioned_writes.\u0027)"}],"source_content_type":"text/x-python","patch_set":18,"id":"7faddb67_a1f1256d","line":1097,"range":{"start_line":1096,"start_character":8,"end_line":1097,"end_character":66},"updated":"2019-08-22 18:21:07.000000000","message":"Better as\n\n use_symlinks \u003d config_true_value(conf.get(\u0027use_symlinks\u0027))\n\n?","commit_id":"6081dca15047588197288dae5dceaf2d77113000"},{"author":{"_account_id":9625,"name":"Thiago da Silva","email":"thiagodasilva@gmail.com","username":"thiago"},"change_message_id":"dd73c8a44268244991b7a3212c73bf1b6c28a782","unresolved":false,"context_lines":[{"line_number":1093,"context_line":""},{"line_number":1094,"context_line":"    use_symlinks \u003d False"},{"line_number":1095,"context_line":"    if config_true_value(conf.get(\u0027allow_versioned_writes\u0027)):"},{"line_number":1096,"context_line":"        if \u0027use_symlinks\u0027 in conf:"},{"line_number":1097,"context_line":"            use_symlinks \u003d config_true_value(conf[\u0027use_symlinks\u0027])"},{"line_number":1098,"context_line":"        if use_symlinks and \u0027symlink\u0027 not in get_swift_info():"},{"line_number":1099,"context_line":"            logger.warning(\u0027symlink middleware is not enabled! Disabling \u0027"},{"line_number":1100,"context_line":"                           \u0027use_symlink in versioned_writes.\u0027)"}],"source_content_type":"text/x-python","patch_set":18,"id":"7faddb67_34cd675e","line":1097,"range":{"start_line":1096,"start_character":8,"end_line":1097,"end_character":66},"in_reply_to":"7faddb67_a1f1256d","updated":"2019-08-26 18:45:09.000000000","message":"Done","commit_id":"6081dca15047588197288dae5dceaf2d77113000"}],"test/functional/test_versioned_writes.py":[{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"fbcc842c304679585740f4ed4164923b3aced748","unresolved":false,"context_lines":[{"line_number":419,"context_line":"        self.assertRaises(ResponseError, versioned_obj.read)"},{"line_number":420,"context_line":""},{"line_number":421,"context_line":"    def assert_most_recent_version(self, obj_name, content,"},{"line_number":422,"context_line":"                                   should_be_dlo\u003dFalse):"},{"line_number":423,"context_line":"        archive_versions \u003d self.env.versions_container.files(parms\u003d{"},{"line_number":424,"context_line":"            \u0027prefix\u0027: \u0027%03x%s/\u0027 % (len(obj_name), obj_name),"},{"line_number":425,"context_line":"            \u0027reverse\u0027: \u0027yes\u0027})"}],"source_content_type":"text/x-python","patch_set":9,"id":"7faddb67_f18f4827","side":"PARENT","line":422,"updated":"2019-08-01 17:42:39.000000000","message":"\"most recent\" here was a bit of a misnomer, it was looking in the versions container which had archived version, but the \"most recent\" was really in the versioned container...\n\nnow everything gets written to the archive container, the \"most recent\" is what\u0027s pointed at by the hardlink in the versoined container and the previous version is at index 1","commit_id":"a0c5197a26008069e210e5a02e071986e3aa4676"},{"author":{"_account_id":9625,"name":"Thiago da Silva","email":"thiagodasilva@gmail.com","username":"thiago"},"change_message_id":"18c55b0494abb3e400e0ba310e03f2bbe3d30739","unresolved":false,"context_lines":[{"line_number":277,"context_line":"        cont_info \u003d container.info()"},{"line_number":278,"context_line":"        self.assertEqual(cont_info[\u0027versions\u0027], quote(versions_container.name))"},{"line_number":279,"context_line":"        expected_content_types \u003d []"},{"line_number":280,"context_line":"        self.assertEqual(expected_content_types, ["},{"line_number":281,"context_line":"            o[\u0027content_type\u0027] for o in versions_container.files("},{"line_number":282,"context_line":"                parms\u003d{\u0027format\u0027: \u0027json\u0027})])"},{"line_number":283,"context_line":"        obj_name \u003d obj_name or Utils.create_name()"}],"source_content_type":"text/x-python","patch_set":15,"id":"7faddb67_6eaed881","line":280,"range":{"start_line":280,"start_character":8,"end_line":280,"end_character":47},"updated":"2019-08-21 15:28:07.000000000","message":"just sanity test, right? maybe write as:\nself.assertTotalVersions(self.env.container, 0)","commit_id":"b2a7005bc7d9ba0610957e73e3f507731b146d2a"},{"author":{"_account_id":9625,"name":"Thiago da Silva","email":"thiagodasilva@gmail.com","username":"thiago"},"change_message_id":"7dd41bf9853425e6fef14d9bdd5be5d5484144f3","unresolved":false,"context_lines":[{"line_number":277,"context_line":"        cont_info \u003d container.info()"},{"line_number":278,"context_line":"        self.assertEqual(cont_info[\u0027versions\u0027], quote(versions_container.name))"},{"line_number":279,"context_line":"        expected_content_types \u003d []"},{"line_number":280,"context_line":"        self.assertEqual(expected_content_types, ["},{"line_number":281,"context_line":"            o[\u0027content_type\u0027] for o in versions_container.files("},{"line_number":282,"context_line":"                parms\u003d{\u0027format\u0027: \u0027json\u0027})])"},{"line_number":283,"context_line":"        obj_name \u003d obj_name or Utils.create_name()"}],"source_content_type":"text/x-python","patch_set":15,"id":"7faddb67_6c61efa8","line":280,"range":{"start_line":280,"start_character":8,"end_line":280,"end_character":47},"in_reply_to":"7faddb67_6eaed881","updated":"2019-08-22 12:12:29.000000000","message":"Done","commit_id":"b2a7005bc7d9ba0610957e73e3f507731b146d2a"},{"author":{"_account_id":9625,"name":"Thiago da Silva","email":"thiagodasilva@gmail.com","username":"thiago"},"change_message_id":"18c55b0494abb3e400e0ba310e03f2bbe3d30739","unresolved":false,"context_lines":[{"line_number":322,"context_line":""},{"line_number":323,"context_line":"        # the old version got saved off"},{"line_number":324,"context_line":"        self.assertTotalVersions(self.env.container, 2)"},{"line_number":325,"context_line":"        versioned_obj_name \u003d versions_container.files()[0]"},{"line_number":326,"context_line":"        prev_version \u003d versions_container.file(versioned_obj_name)"},{"line_number":327,"context_line":"        prev_version.initialize()"},{"line_number":328,"context_line":"        self.assertEqual(b\"aaaaa\", prev_version.read())"},{"line_number":329,"context_line":"        self.assertEqual(prev_version.content_type, \u0027text/jibberish01\u0027)"},{"line_number":330,"context_line":""},{"line_number":331,"context_line":"        resp_headers \u003d {"},{"line_number":332,"context_line":"            h.lower(): v for h, v in prev_version.conn.response.getheaders()}"}],"source_content_type":"text/x-python","patch_set":15,"id":"7faddb67_6e9b3816","line":329,"range":{"start_line":325,"start_character":8,"end_line":329,"end_character":71},"updated":"2019-08-21 15:28:07.000000000","message":"interesting, why did you not need to add \"if self.env.use_symlinks here? I\u0027d expect when use_symlinks\u003dTrue that versions_container.files()[0] would be the object with content \u003d \"bbbbb\". What am i missing?","commit_id":"b2a7005bc7d9ba0610957e73e3f507731b146d2a"},{"author":{"_account_id":9625,"name":"Thiago da Silva","email":"thiagodasilva@gmail.com","username":"thiago"},"change_message_id":"18c55b0494abb3e400e0ba310e03f2bbe3d30739","unresolved":false,"context_lines":[{"line_number":337,"context_line":"        # make sure the new obj metadata did not leak to the prev. version"},{"line_number":338,"context_line":"        self.assertNotIn(\u0027foo\u0027, prev_version.metadata)"},{"line_number":339,"context_line":""},{"line_number":340,"context_line":"        # check that POST does not create a new version"},{"line_number":341,"context_line":"        versioned_obj.sync_metadata(metadata\u003d{\u0027fu\u0027: \u0027baz\u0027})"},{"line_number":342,"context_line":"        self.assertTotalVersions(self.env.container, 2)"},{"line_number":343,"context_line":""}],"source_content_type":"text/x-python","patch_set":15,"id":"7faddb67_2e60e000","line":340,"range":{"start_line":340,"start_character":10,"end_line":340,"end_character":55},"updated":"2019-08-21 15:28:07.000000000","message":"ok, down below we have a test to for checking POSTs made it down to the actual object in case of symlink versioning","commit_id":"b2a7005bc7d9ba0610957e73e3f507731b146d2a"},{"author":{"_account_id":9625,"name":"Thiago da Silva","email":"thiagodasilva@gmail.com","username":"thiago"},"change_message_id":"18c55b0494abb3e400e0ba310e03f2bbe3d30739","unresolved":false,"context_lines":[{"line_number":654,"context_line":"        # this could be a helpful scenario for dev ops that want to setup"},{"line_number":655,"context_line":"        # just one container to hold object versions of multiple containers"},{"line_number":656,"context_line":"        # and each one of those containers are owned by different users"},{"line_number":657,"context_line":"        self.assertTrue(versioned_obj.sync_metadata(metadata\u003d{\u0027foo\u0027: \u0027bar\u0027}))"},{"line_number":658,"context_line":"        self.assertTrue(versioned_obj.delete("},{"line_number":659,"context_line":"                        cfg\u003d{\u0027use_token\u0027: self.env.storage_token2}))"},{"line_number":660,"context_line":""}],"source_content_type":"text/x-python","patch_set":15,"id":"7faddb67_900572c4","line":657,"range":{"start_line":657,"start_character":8,"end_line":657,"end_character":77},"updated":"2019-08-21 15:28:07.000000000","message":"missing use_token?","commit_id":"b2a7005bc7d9ba0610957e73e3f507731b146d2a"},{"author":{"_account_id":9625,"name":"Thiago da Silva","email":"thiagodasilva@gmail.com","username":"thiago"},"change_message_id":"7dd41bf9853425e6fef14d9bdd5be5d5484144f3","unresolved":false,"context_lines":[{"line_number":654,"context_line":"        # this could be a helpful scenario for dev ops that want to setup"},{"line_number":655,"context_line":"        # just one container to hold object versions of multiple containers"},{"line_number":656,"context_line":"        # and each one of those containers are owned by different users"},{"line_number":657,"context_line":"        self.assertTrue(versioned_obj.sync_metadata(metadata\u003d{\u0027foo\u0027: \u0027bar\u0027}))"},{"line_number":658,"context_line":"        self.assertTrue(versioned_obj.delete("},{"line_number":659,"context_line":"                        cfg\u003d{\u0027use_token\u0027: self.env.storage_token2}))"},{"line_number":660,"context_line":""}],"source_content_type":"text/x-python","patch_set":15,"id":"7faddb67_acc28752","line":657,"range":{"start_line":657,"start_character":8,"end_line":657,"end_character":77},"in_reply_to":"7faddb67_900572c4","updated":"2019-08-22 12:12:29.000000000","message":"Done","commit_id":"b2a7005bc7d9ba0610957e73e3f507731b146d2a"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"cdd9e9260f8230a2d1616eeb8d54207fb1f154fa","unresolved":false,"context_lines":[{"line_number":80,"context_line":"        cls.versioning_enabled \u003d \u0027versions\u0027 in container_info"},{"line_number":81,"context_line":""},{"line_number":82,"context_line":"        # newer swift deployments should be using symlink based versions"},{"line_number":83,"context_line":"        cls.use_symlinks \u003d cls.conn.cluster_info().get("},{"line_number":84,"context_line":"            \u0027versioned_writes\u0027, {}).get(\u0027use_symlinks\u0027, False)"},{"line_number":85,"context_line":""},{"line_number":86,"context_line":"        if not tf.skip2:"}],"source_content_type":"text/x-python","patch_set":16,"id":"7faddb67_b9a419ba","line":83,"range":{"start_line":83,"start_character":27,"end_line":83,"end_character":50},"updated":"2019-08-21 20:45:52.000000000","message":"Not tf.cluster_info.get(...)?","commit_id":"cbc9e052491a9dc36f6920489d6bb395d23d5533"},{"author":{"_account_id":9625,"name":"Thiago da Silva","email":"thiagodasilva@gmail.com","username":"thiago"},"change_message_id":"7dd41bf9853425e6fef14d9bdd5be5d5484144f3","unresolved":false,"context_lines":[{"line_number":80,"context_line":"        cls.versioning_enabled \u003d \u0027versions\u0027 in container_info"},{"line_number":81,"context_line":""},{"line_number":82,"context_line":"        # newer swift deployments should be using symlink based versions"},{"line_number":83,"context_line":"        cls.use_symlinks \u003d cls.conn.cluster_info().get("},{"line_number":84,"context_line":"            \u0027versioned_writes\u0027, {}).get(\u0027use_symlinks\u0027, False)"},{"line_number":85,"context_line":""},{"line_number":86,"context_line":"        if not tf.skip2:"}],"source_content_type":"text/x-python","patch_set":16,"id":"7faddb67_2c15374a","line":83,"range":{"start_line":83,"start_character":27,"end_line":83,"end_character":50},"in_reply_to":"7faddb67_b9a419ba","updated":"2019-08-22 12:12:29.000000000","message":"Done","commit_id":"cbc9e052491a9dc36f6920489d6bb395d23d5533"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"cdd9e9260f8230a2d1616eeb8d54207fb1f154fa","unresolved":false,"context_lines":[{"line_number":247,"context_line":"    @property"},{"line_number":248,"context_line":"    def account_name(self):"},{"line_number":249,"context_line":"        if not self._account_name:"},{"line_number":250,"context_line":"            self._account_name \u003d self.env.conn.storage_path.rsplit(\u0027/\u0027, 1)[-1]"},{"line_number":251,"context_line":"        return self._account_name"},{"line_number":252,"context_line":""},{"line_number":253,"context_line":"    def assertTotalVersions(self, versioned_container, count):"}],"source_content_type":"text/x-python","patch_set":16,"id":"7faddb67_7998e167","line":250,"range":{"start_line":250,"start_character":47,"end_line":250,"end_character":59},"updated":"2019-08-21 20:45:52.000000000","message":"I take it this never ends with a slash...","commit_id":"cbc9e052491a9dc36f6920489d6bb395d23d5533"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"cdd9e9260f8230a2d1616eeb8d54207fb1f154fa","unresolved":false,"context_lines":[{"line_number":255,"context_line":"        versions_container \u003d self.env.account.container(versions_location)"},{"line_number":256,"context_line":"        if not self.env.use_symlinks:"},{"line_number":257,"context_line":"            # there\u0027s one less \"version\" for each \"versioned\" obj"},{"line_number":258,"context_line":"            count -\u003d versioned_container.info()[\u0027object_count\u0027]"},{"line_number":259,"context_line":"        self.assertEqual(count, versions_container.info()[\u0027object_count\u0027])"},{"line_number":260,"context_line":""},{"line_number":261,"context_line":"    def test_clear_version_option(self):"}],"source_content_type":"text/x-python","patch_set":16,"id":"7faddb67_df41b537","line":258,"updated":"2019-08-21 20:45:52.000000000","message":"I wonder if it\u0027d be more clear/obvious to do something like\n\n if self.env.use_symlinks:\n     self.assertEqual(count, versions_container.info()[\u0027object_count\u0027])\n else:\n     self.assertEqual(count, versioned_container.info()[\u0027object_count\u0027] +\n                             versions_container.info()[\u0027object_count\u0027])\n\n*shrug*","commit_id":"cbc9e052491a9dc36f6920489d6bb395d23d5533"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"cdd9e9260f8230a2d1616eeb8d54207fb1f154fa","unresolved":false,"context_lines":[{"line_number":256,"context_line":"        if not self.env.use_symlinks:"},{"line_number":257,"context_line":"            # there\u0027s one less \"version\" for each \"versioned\" obj"},{"line_number":258,"context_line":"            count -\u003d versioned_container.info()[\u0027object_count\u0027]"},{"line_number":259,"context_line":"        self.assertEqual(count, versions_container.info()[\u0027object_count\u0027])"},{"line_number":260,"context_line":""},{"line_number":261,"context_line":"    def test_clear_version_option(self):"},{"line_number":262,"context_line":"        # sanity"}],"source_content_type":"text/x-python","patch_set":16,"id":"7faddb67_d9a8f578","line":259,"range":{"start_line":259,"start_character":51,"end_line":259,"end_character":55},"updated":"2019-08-21 20:45:52.000000000","message":"nit: second head","commit_id":"cbc9e052491a9dc36f6920489d6bb395d23d5533"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"cdd9e9260f8230a2d1616eeb8d54207fb1f154fa","unresolved":false,"context_lines":[{"line_number":313,"context_line":"        if self.env.use_symlinks:"},{"line_number":314,"context_line":"            expected_content_types.append(\u0027text/jibberish02\u0027)"},{"line_number":315,"context_line":"        else:"},{"line_number":316,"context_line":"            expected_content_types.append(\u0027text/jibberish01\u0027)"},{"line_number":317,"context_line":"        self.assertEqual(expected_content_types, ["},{"line_number":318,"context_line":"            o[\u0027content_type\u0027] for o in versions_container.files("},{"line_number":319,"context_line":"                parms\u003d{\u0027format\u0027: \u0027json\u0027})])"}],"source_content_type":"text/x-python","patch_set":16,"id":"7faddb67_39cca95f","line":316,"updated":"2019-08-21 20:45:52.000000000","message":"IDK -- I wonder if it\u0027d be better to just have one set of appends... I\u0027m\u0027a see what I can whip up.","commit_id":"cbc9e052491a9dc36f6920489d6bb395d23d5533"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"cdd9e9260f8230a2d1616eeb8d54207fb1f154fa","unresolved":false,"context_lines":[{"line_number":729,"context_line":"        expected_count +\u003d 1"},{"line_number":730,"context_line":"        self.assertEqual(b\"bbbbb\", symlink.read())"},{"line_number":731,"context_line":""},{"line_number":732,"context_line":"        self.assertTotalVersions(container, expected_count)"},{"line_number":733,"context_line":"        all_versions \u003d versions_container.files(parms\u003d{\u0027format\u0027: \u0027json\u0027})"},{"line_number":734,"context_line":"        for version_info in all_versions:"},{"line_number":735,"context_line":"            if version_info[\u0027name\u0027][3:].startswith(symlink_name):"}],"source_content_type":"text/x-python","patch_set":16,"id":"7faddb67_dfb69525","line":732,"range":{"start_line":732,"start_character":44,"end_line":732,"end_character":58},"updated":"2019-08-21 20:45:52.000000000","message":"Should this just be hard-coded at 4?","commit_id":"cbc9e052491a9dc36f6920489d6bb395d23d5533"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"cdd9e9260f8230a2d1616eeb8d54207fb1f154fa","unresolved":false,"context_lines":[{"line_number":733,"context_line":"        all_versions \u003d versions_container.files(parms\u003d{\u0027format\u0027: \u0027json\u0027})"},{"line_number":734,"context_line":"        for version_info in all_versions:"},{"line_number":735,"context_line":"            if version_info[\u0027name\u0027][3:].startswith(symlink_name):"},{"line_number":736,"context_line":"                versioned_obj_name \u003d version_info[\u0027name\u0027]"},{"line_number":737,"context_line":"                break"},{"line_number":738,"context_line":"        else:"},{"line_number":739,"context_line":"            self.fail(\"Couldn\u0027t find any versions of %s in %r\" % ("}],"source_content_type":"text/x-python","patch_set":16,"id":"7faddb67_7f60c1a5","line":736,"updated":"2019-08-21 20:45:52.000000000","message":"Can we use our handy new _find_previous_version() here?","commit_id":"cbc9e052491a9dc36f6920489d6bb395d23d5533"},{"author":{"_account_id":9625,"name":"Thiago da Silva","email":"thiagodasilva@gmail.com","username":"thiago"},"change_message_id":"7dd41bf9853425e6fef14d9bdd5be5d5484144f3","unresolved":false,"context_lines":[{"line_number":733,"context_line":"        all_versions \u003d versions_container.files(parms\u003d{\u0027format\u0027: \u0027json\u0027})"},{"line_number":734,"context_line":"        for version_info in all_versions:"},{"line_number":735,"context_line":"            if version_info[\u0027name\u0027][3:].startswith(symlink_name):"},{"line_number":736,"context_line":"                versioned_obj_name \u003d version_info[\u0027name\u0027]"},{"line_number":737,"context_line":"                break"},{"line_number":738,"context_line":"        else:"},{"line_number":739,"context_line":"            self.fail(\"Couldn\u0027t find any versions of %s in %r\" % ("}],"source_content_type":"text/x-python","patch_set":16,"id":"7faddb67_2fb3e9eb","line":736,"in_reply_to":"7faddb67_7f60c1a5","updated":"2019-08-22 12:12:29.000000000","message":"Done","commit_id":"cbc9e052491a9dc36f6920489d6bb395d23d5533"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"cdd9e9260f8230a2d1616eeb8d54207fb1f154fa","unresolved":false,"context_lines":[{"line_number":800,"context_line":"                         symlink.info(parms\u003d{"},{"line_number":801,"context_line":"                             \u0027symlink\u0027: \u0027get\u0027})[\u0027content_type\u0027])"},{"line_number":802,"context_line":""},{"line_number":803,"context_line":"    def _find_previous_version(self, versions_container, name):"},{"line_number":804,"context_line":"        name_len \u003d len(name if six.PY2 else name.encode(\u0027utf8\u0027))"},{"line_number":805,"context_line":"        version_container_files \u003d self.env.versions_container.files(parms\u003d{"},{"line_number":806,"context_line":"            \u0027format\u0027: \u0027json\u0027,"}],"source_content_type":"text/x-python","patch_set":16,"id":"7faddb67_3f3d698d","line":803,"updated":"2019-08-21 20:45:52.000000000","message":"Out-of-scope: I really feel like we ought to have a proper (client-exposed) API for this sort of thing :-/","commit_id":"cbc9e052491a9dc36f6920489d6bb395d23d5533"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"cdd9e9260f8230a2d1616eeb8d54207fb1f154fa","unresolved":false,"context_lines":[{"line_number":861,"context_line":"        symlink.write(b\u0027this is not a symlink\u0027)"},{"line_number":862,"context_line":"        self.assertTotalVersions(self.env.container, 3)"},{"line_number":863,"context_line":""},{"line_number":864,"context_line":"        # find previous version"},{"line_number":865,"context_line":"        version_container_files \u003d self.env.versions_container.files()"},{"line_number":866,"context_line":"        for obj in version_container_files:"},{"line_number":867,"context_line":"            if obj[3:].startswith(symlink.name):"}],"source_content_type":"text/x-python","patch_set":16,"id":"7faddb67_5f270564","line":864,"updated":"2019-08-21 20:45:52.000000000","message":"This *really* feels like it should be able to use _find_previous_version()","commit_id":"cbc9e052491a9dc36f6920489d6bb395d23d5533"},{"author":{"_account_id":9625,"name":"Thiago da Silva","email":"thiagodasilva@gmail.com","username":"thiago"},"change_message_id":"7dd41bf9853425e6fef14d9bdd5be5d5484144f3","unresolved":false,"context_lines":[{"line_number":861,"context_line":"        symlink.write(b\u0027this is not a symlink\u0027)"},{"line_number":862,"context_line":"        self.assertTotalVersions(self.env.container, 3)"},{"line_number":863,"context_line":""},{"line_number":864,"context_line":"        # find previous version"},{"line_number":865,"context_line":"        version_container_files \u003d self.env.versions_container.files()"},{"line_number":866,"context_line":"        for obj in version_container_files:"},{"line_number":867,"context_line":"            if obj[3:].startswith(symlink.name):"}],"source_content_type":"text/x-python","patch_set":16,"id":"7faddb67_8fd69df2","line":864,"in_reply_to":"7faddb67_5f270564","updated":"2019-08-22 12:12:29.000000000","message":"Done","commit_id":"cbc9e052491a9dc36f6920489d6bb395d23d5533"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"cdd9e9260f8230a2d1616eeb8d54207fb1f154fa","unresolved":false,"context_lines":[{"line_number":1180,"context_line":"            \u0027reverse\u0027: \u0027true\u0027,"},{"line_number":1181,"context_line":"        })"},{"line_number":1182,"context_line":"        if self.use_symlinks:"},{"line_number":1183,"context_line":"            self.assertEqual(2, len(versions_list))"},{"line_number":1184,"context_line":"            old_version \u003d versions_list[1]"},{"line_number":1185,"context_line":"        else:"},{"line_number":1186,"context_line":"            self.assertEqual(1, len(versions_list))"}],"source_content_type":"text/x-python","patch_set":16,"id":"7faddb67_9fbb3dc2","line":1183,"updated":"2019-08-21 20:45:52.000000000","message":"Not using our fancy new assertTotalVersions() or _find_previous_version()? I suppose we don\u0027t subclass from TestObjectVersioning, which is why we needed to reimplement account_name...\n\nShould we fix *that*? Maybe it\u0027s too much scope creep...","commit_id":"cbc9e052491a9dc36f6920489d6bb395d23d5533"},{"author":{"_account_id":9625,"name":"Thiago da Silva","email":"thiagodasilva@gmail.com","username":"thiago"},"change_message_id":"dd73c8a44268244991b7a3212c73bf1b6c28a782","unresolved":false,"context_lines":[{"line_number":1254,"context_line":"        self.conn.authenticate()"},{"line_number":1255,"context_line":"        self.account \u003d Account("},{"line_number":1256,"context_line":"            self.conn, tf.config.get(\u0027account\u0027, tf.config[\u0027username\u0027]))"},{"line_number":1257,"context_line":"        self.account.delete_containers()"},{"line_number":1258,"context_line":"        self._account_name \u003d None"},{"line_number":1259,"context_line":""},{"line_number":1260,"context_line":"        # create target container"}],"source_content_type":"text/x-python","patch_set":17,"id":"7faddb67_fbc91351","line":1257,"range":{"start_line":1257,"start_character":8,"end_line":1257,"end_character":40},"updated":"2019-08-26 18:45:09.000000000","message":"add tearDown method to also cleanup after tests are run","commit_id":"0141140aa6a4301a04cb4b292179f985bf7d82fe"},{"author":{"_account_id":9625,"name":"Thiago da Silva","email":"thiagodasilva@gmail.com","username":"thiago"},"change_message_id":"dd73c8a44268244991b7a3212c73bf1b6c28a782","unresolved":false,"context_lines":[{"line_number":1303,"context_line":"    def test_versioned_put_get_head(self):"},{"line_number":1304,"context_line":"        obj_name \u003d Utils.create_name()"},{"line_number":1305,"context_line":"        obj \u003d self.container.file(obj_name)"},{"line_number":1306,"context_line":"        obj.write(b\u0027version1\u0027, hdrs\u003d{\u0027Content-Type\u0027: \u0027text/jibberish09\u0027})"},{"line_number":1307,"context_line":""},{"line_number":1308,"context_line":"        archive_files \u003d self.target_container.files(parms\u003d{\u0027format\u0027: \u0027json\u0027})"},{"line_number":1309,"context_line":"        self.assertEqual(1, len(archive_files))"}],"source_content_type":"text/x-python","patch_set":17,"id":"7faddb67_5b270720","line":1306,"updated":"2019-08-26 18:45:09.000000000","message":"save etag here to use in assertEqual later","commit_id":"0141140aa6a4301a04cb4b292179f985bf7d82fe"},{"author":{"_account_id":9625,"name":"Thiago da Silva","email":"thiagodasilva@gmail.com","username":"thiago"},"change_message_id":"dd73c8a44268244991b7a3212c73bf1b6c28a782","unresolved":false,"context_lines":[{"line_number":1756,"context_line":"        # now, turn off versioning"},{"line_number":1757,"context_line":"        self.container.update_metadata(hdrs\u003d{\u0027X-Versions-Location\u0027: \u0027\u0027})"},{"line_number":1758,"context_line":""},{"line_number":1759,"context_line":"        # POST to symlink created by versoined writes is *always* redirected"},{"line_number":1760,"context_line":"        # automatically"},{"line_number":1761,"context_line":"        obj.post(hdrs\u003d{\u0027Content-Type\u0027: \u0027text/updated20\u0027})"},{"line_number":1762,"context_line":"        self.assertEqual(self.conn.response.status, 202)"}],"source_content_type":"text/x-python","patch_set":17,"id":"7faddb67_5b9147f7","line":1759,"range":{"start_line":1759,"start_character":37,"end_line":1759,"end_character":46},"updated":"2019-08-26 18:45:09.000000000","message":"nit: spelling","commit_id":"0141140aa6a4301a04cb4b292179f985bf7d82fe"},{"author":{"_account_id":9625,"name":"Thiago da Silva","email":"thiagodasilva@gmail.com","username":"thiago"},"change_message_id":"dd73c8a44268244991b7a3212c73bf1b6c28a782","unresolved":false,"context_lines":[{"line_number":1756,"context_line":"        # now, turn off versioning"},{"line_number":1757,"context_line":"        self.container.update_metadata(hdrs\u003d{\u0027X-Versions-Location\u0027: \u0027\u0027})"},{"line_number":1758,"context_line":""},{"line_number":1759,"context_line":"        # POST to symlink created by versoined writes is *always* redirected"},{"line_number":1760,"context_line":"        # automatically"},{"line_number":1761,"context_line":"        obj.post(hdrs\u003d{\u0027Content-Type\u0027: \u0027text/updated20\u0027})"},{"line_number":1762,"context_line":"        self.assertEqual(self.conn.response.status, 202)"}],"source_content_type":"text/x-python","patch_set":17,"id":"7faddb67_db8457b5","line":1759,"range":{"start_line":1759,"start_character":57,"end_line":1759,"end_character":65},"updated":"2019-08-26 18:45:09.000000000","message":"whooaa, this is nice, even when versioning is turned off after the fact, it will still POST correclty","commit_id":"0141140aa6a4301a04cb4b292179f985bf7d82fe"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"5b5100869d4d1f0b13a2fc35ea54118844a79d65","unresolved":false,"context_lines":[{"line_number":1756,"context_line":"        # now, turn off versioning"},{"line_number":1757,"context_line":"        self.container.update_metadata(hdrs\u003d{\u0027X-Versions-Location\u0027: \u0027\u0027})"},{"line_number":1758,"context_line":""},{"line_number":1759,"context_line":"        # POST to symlink created by versoined writes is *always* redirected"},{"line_number":1760,"context_line":"        # automatically"},{"line_number":1761,"context_line":"        obj.post(hdrs\u003d{\u0027Content-Type\u0027: \u0027text/updated20\u0027})"},{"line_number":1762,"context_line":"        self.assertEqual(self.conn.response.status, 202)"}],"source_content_type":"text/x-python","patch_set":17,"id":"7faddb67_ee4037a5","line":1759,"range":{"start_line":1759,"start_character":57,"end_line":1759,"end_character":65},"in_reply_to":"7faddb67_db8457b5","updated":"2019-08-26 21:16:59.000000000","message":":O\n\nI\u0027m...not sure whether I like this or not. On the one hand, it more-closely mirrors the pre-symlink behavior. On the other,\n\n- I\u0027d generally expect that turning off versioning should stop writes going to the archive container; this breaks that expectation.\n- The data in the archive container may have been overwritten, bringing back questions about what we can/should do for POSTs to \"broken\" static links.\n\nIn particular, being able to POST X-Delete-After: 1 to an object in the archive container (where you don\u0027t necessarily have write access)... it makes me a little nervous.","commit_id":"0141140aa6a4301a04cb4b292179f985bf7d82fe"},{"author":{"_account_id":9625,"name":"Thiago da Silva","email":"thiagodasilva@gmail.com","username":"thiago"},"change_message_id":"e0ed1637ce1d533803b9d895befaa871ce10f1ec","unresolved":false,"context_lines":[{"line_number":1756,"context_line":"        # now, turn off versioning"},{"line_number":1757,"context_line":"        self.container.update_metadata(hdrs\u003d{\u0027X-Versions-Location\u0027: \u0027\u0027})"},{"line_number":1758,"context_line":""},{"line_number":1759,"context_line":"        # POST to symlink created by versoined writes is *always* redirected"},{"line_number":1760,"context_line":"        # automatically"},{"line_number":1761,"context_line":"        obj.post(hdrs\u003d{\u0027Content-Type\u0027: \u0027text/updated20\u0027})"},{"line_number":1762,"context_line":"        self.assertEqual(self.conn.response.status, 202)"}],"source_content_type":"text/x-python","patch_set":17,"id":"7faddb67_15befbad","line":1759,"range":{"start_line":1759,"start_character":57,"end_line":1759,"end_character":65},"in_reply_to":"7faddb67_ee4037a5","updated":"2019-08-27 10:19:28.000000000","message":"From a user\u0027s perspective using symlinks or not and where the data actually resides should be irrelevant. Even if the user turned off versioning. The obj that he/she has access to read and write, should still allow him to POST also. The behavior from the user\u0027s POV should be seamless.","commit_id":"0141140aa6a4301a04cb4b292179f985bf7d82fe"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"571fcc99eda5828d26575fba392cacf1fb36fc6d","unresolved":false,"context_lines":[{"line_number":651,"context_line":"                          cfg\u003d{\u0027use_token\u0027: self.env.storage_token2})"},{"line_number":652,"context_line":""},{"line_number":653,"context_line":"        # but is able to POST and DELETE from the source container"},{"line_number":654,"context_line":"        # this could be a helpful scenario for dev ops that want to setup"},{"line_number":655,"context_line":"        # just one container to hold object versions of multiple containers"},{"line_number":656,"context_line":"        # and each one of those containers are owned by different users"},{"line_number":657,"context_line":"        self.assertTrue(versioned_obj.sync_metadata("},{"line_number":658,"context_line":"            metadata\u003d{\u0027foo\u0027: \u0027bar\u0027},"}],"source_content_type":"text/x-python","patch_set":18,"id":"7faddb67_5b2dc7ac","line":655,"range":{"start_line":654,"start_character":47,"end_line":655,"end_character":75},"updated":"2019-08-22 18:21:07.000000000","message":"Off-topic: that sounds like a *terrible* idea, even before we get to questions of ownership for the multiple containers...","commit_id":"6081dca15047588197288dae5dceaf2d77113000"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"571fcc99eda5828d26575fba392cacf1fb36fc6d","unresolved":false,"context_lines":[{"line_number":656,"context_line":"        # and each one of those containers are owned by different users"},{"line_number":657,"context_line":"        self.assertTrue(versioned_obj.sync_metadata("},{"line_number":658,"context_line":"            metadata\u003d{\u0027foo\u0027: \u0027bar\u0027},"},{"line_number":659,"context_line":"            cfg\u003d{\u0027use_token\u0027: self.env.storage_token2}))"},{"line_number":660,"context_line":"        self.assertTrue(versioned_obj.delete("},{"line_number":661,"context_line":"                        cfg\u003d{\u0027use_token\u0027: self.env.storage_token2}))"},{"line_number":662,"context_line":""}],"source_content_type":"text/x-python","patch_set":18,"id":"7faddb67_db20d7b4","line":659,"updated":"2019-08-22 18:21:07.000000000","message":"Good catch!","commit_id":"6081dca15047588197288dae5dceaf2d77113000"}],"test/unit/common/middleware/helpers.py":[{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"cdd9e9260f8230a2d1616eeb8d54207fb1f154fa","unresolved":false,"context_lines":[{"line_number":62,"context_line":"        self.uploaded \u003d {}"},{"line_number":63,"context_line":"        # mapping of (method, path) --\u003e (response class, headers, body)"},{"line_number":64,"context_line":"        self._responses \u003d {}"},{"line_number":65,"context_line":"        self.logger \u003d debug_logger(\u0027fake-swift\u0027)"},{"line_number":66,"context_line":"        self.account_ring \u003d FakeRing()"},{"line_number":67,"context_line":"        self.container_ring \u003d FakeRing()"},{"line_number":68,"context_line":"        self.get_object_ring \u003d lambda policy_index: FakeRing()"}],"source_content_type":"text/x-python","patch_set":16,"id":"7faddb67_2a3c45bd","line":65,"updated":"2019-08-21 20:45:52.000000000","message":"I never remember the difference between these... I take it debug_logger shows the messages when there\u0027s a test failure?","commit_id":"cbc9e052491a9dc36f6920489d6bb395d23d5533"}],"test/unit/common/middleware/test_symlink.py":[{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"0226346303630ebb6f88390acc031316ac6a2e1a","unresolved":false,"context_lines":[{"line_number":947,"context_line":"        self.sym \u003d symlink.filter_factory(conf)(self.app)"},{"line_number":948,"context_line":"        self.sym.logger \u003d self.app.logger"},{"line_number":949,"context_line":"        vw_conf \u003d {\u0027allow_versioned_writes\u0027: \u0027true\u0027}"},{"line_number":950,"context_line":"        self.vw \u003d versioned_writes.filter_factory(vw_conf)(self.sym)"},{"line_number":951,"context_line":""},{"line_number":952,"context_line":"    def call_vw(self, req, **kwargs):"},{"line_number":953,"context_line":"        return self.call_app(req, app\u003dself.vw, **kwargs)"}],"source_content_type":"text/x-python","patch_set":8,"id":"7faddb67_1f7b74be","line":950,"updated":"2019-07-25 20:37:28.000000000","message":"so our pipeline already had vw \u0026 symlinks","commit_id":"10d64be4f9f63fa8af122aae2d9fee76027587f5"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"0226346303630ebb6f88390acc031316ac6a2e1a","unresolved":false,"context_lines":[{"line_number":957,"context_line":"        self.assertEqual(req.path, other.path)"},{"line_number":958,"context_line":""},{"line_number":959,"context_line":"    def test_no_symlinks_PUT_overwrite_symlink_with_symlink(self):"},{"line_number":960,"context_line":"        self.vw.use_symlinks \u003d False"},{"line_number":961,"context_line":"        self.app.register("},{"line_number":962,"context_line":"            \u0027PUT\u0027, \u0027/v1/a/c/symlink\u0027, swob.HTTPCreated,"},{"line_number":963,"context_line":"            {\u0027X-Symlink-Target\u0027: \u0027new_cont/new_tgt\u0027,"}],"source_content_type":"text/x-python","patch_set":8,"id":"7faddb67_7f6ce807","line":960,"updated":"2019-07-25 20:37:28.000000000","message":"so I guess with the legacy use_symlinks \u003d False there\u0027s not much churn","commit_id":"10d64be4f9f63fa8af122aae2d9fee76027587f5"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"0226346303630ebb6f88390acc031316ac6a2e1a","unresolved":false,"context_lines":[{"line_number":998,"context_line":""},{"line_number":999,"context_line":"    @mock.patch(\u0027swift.common.middleware.versioned_writes.time.time\u0027,"},{"line_number":1000,"context_line":"                return_value\u003d1234)"},{"line_number":1001,"context_line":"    def test_PUT_overwrite_symlink_with_symlink(self, mock_time):"},{"line_number":1002,"context_line":"        self.app.register("},{"line_number":1003,"context_line":"            \u0027GET\u0027, \u0027/v1/a/c/symlink\u0027, swob.HTTPOk,"},{"line_number":1004,"context_line":"            {\u0027last-modified\u0027: \u0027Thu, 1 Jan 1970 00:00:01 GMT\u0027,"}],"source_content_type":"text/x-python","patch_set":8,"id":"7faddb67_3f7670da","line":1001,"updated":"2019-07-25 20:37:28.000000000","message":"and all the new tests are for use_symlinks mode...\n\nbut that\u0027s only hitting the new symlink extend incidentally","commit_id":"10d64be4f9f63fa8af122aae2d9fee76027587f5"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"571fcc99eda5828d26575fba392cacf1fb36fc6d","unresolved":false,"context_lines":[{"line_number":1141,"context_line":"            \u0027\"name\": \"003sym/1\", \u0027"},{"line_number":1142,"context_line":"            \u0027\"content_type\": \"text/plain\"}]\u0027)"},{"line_number":1143,"context_line":"        self.app.register("},{"line_number":1144,"context_line":"            \u0027GET\u0027, \u0027/v1/a/ver_cont/003sym/2\u0027, swob.HTTPCreated,"},{"line_number":1145,"context_line":"            {\u0027content-length\u0027: \u00270\u0027,"},{"line_number":1146,"context_line":"             \u0027X-Object-Sysmeta-Symlink-Target\u0027: \u0027c/tgt\u0027}, None)"},{"line_number":1147,"context_line":"        self.app.register("}],"source_content_type":"text/x-python","patch_set":18,"id":"7faddb67_e3f405d3","side":"PARENT","line":1144,"range":{"start_line":1144,"start_character":51,"end_line":1144,"end_character":62},"updated":"2019-08-22 18:21:07.000000000","message":"heh, whoops","commit_id":"f70520239c7fa2d22e4b9ee604bfaf7123b39095"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"571fcc99eda5828d26575fba392cacf1fb36fc6d","unresolved":false,"context_lines":[{"line_number":1155,"context_line":"        cache \u003d FakeCache({\u0027sysmeta\u0027: {\u0027versions-location\u0027: \u0027ver_cont\u0027}})"},{"line_number":1156,"context_line":"        req \u003d Request.blank("},{"line_number":1157,"context_line":"            \u0027/v1/a/c/sym\u0027,"},{"line_number":1158,"context_line":"            headers\u003d{\u0027X-If-Delete-At\u0027: 1},"},{"line_number":1159,"context_line":"            environ\u003d{\u0027REQUEST_METHOD\u0027: \u0027DELETE\u0027, \u0027swift.cache\u0027: cache,"},{"line_number":1160,"context_line":"                     \u0027CONTENT_LENGTH\u0027: \u00270\u0027, \u0027swift.trans_id\u0027: \u0027fake_trans_id\u0027})"},{"line_number":1161,"context_line":"        status, headers, body \u003d self.call_vw(req)"}],"source_content_type":"text/x-python","patch_set":18,"id":"7faddb67_a6b4db37","side":"PARENT","line":1158,"range":{"start_line":1158,"start_character":21,"end_line":1158,"end_character":40},"updated":"2019-08-22 18:21:07.000000000","message":"Wait, we were exercising what now?","commit_id":"f70520239c7fa2d22e4b9ee604bfaf7123b39095"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"571fcc99eda5828d26575fba392cacf1fb36fc6d","unresolved":false,"context_lines":[{"line_number":1162,"context_line":"        self.assertEqual(status, \u0027200 OK\u0027)"},{"line_number":1163,"context_line":"        self.assertEqual(len(self.authorized), 1)"},{"line_number":1164,"context_line":"        self.assertRequestEqual(req, self.authorized[0])"},{"line_number":1165,"context_line":"        self.assertEqual(4, self.app.call_count)"},{"line_number":1166,"context_line":"        self.assertEqual([\u0027VW\u0027, \u0027VW\u0027, \u0027VW\u0027, \u0027VW\u0027], self.app.swift_sources)"},{"line_number":1167,"context_line":"        self.assertEqual({\u0027fake_trans_id\u0027}, set(self.app.txn_ids))"},{"line_number":1168,"context_line":"        calls \u003d self.app.calls_with_headers"}],"source_content_type":"text/x-python","patch_set":18,"id":"7faddb67_237f7de0","side":"PARENT","line":1165,"updated":"2019-08-22 18:21:07.000000000","message":"lol! We never actually looked at what the calls were, or in what order!?","commit_id":"f70520239c7fa2d22e4b9ee604bfaf7123b39095"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"571fcc99eda5828d26575fba392cacf1fb36fc6d","unresolved":false,"context_lines":[{"line_number":1171,"context_line":"        self.assertEqual(\u0027/v1/a/c/sym\u0027, path)"},{"line_number":1172,"context_line":"        self.assertEqual("},{"line_number":1173,"context_line":"            \u0027c/tgt\u0027,"},{"line_number":1174,"context_line":"            req_headers[\u0027X-Object-Sysmeta-Symlink-Target\u0027])"},{"line_number":1175,"context_line":""},{"line_number":1176,"context_line":""},{"line_number":1177,"context_line":"class TestSymlinkContainerContext(TestSymlinkMiddlewareBase):"}],"source_content_type":"text/x-python","patch_set":18,"id":"7faddb67_a3728d11","side":"PARENT","line":1174,"updated":"2019-08-22 18:21:07.000000000","message":"...just that the third one was a PUT of a symlink...","commit_id":"f70520239c7fa2d22e4b9ee604bfaf7123b39095"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"571fcc99eda5828d26575fba392cacf1fb36fc6d","unresolved":false,"context_lines":[{"line_number":1138,"context_line":"        self.app.register("},{"line_number":1139,"context_line":"            \u0027PUT\u0027, \u0027/v1/a/ver_cont/007symlink/0000000001.00000\u0027,"},{"line_number":1140,"context_line":"            swob.HTTPCreated,"},{"line_number":1141,"context_line":"            {\u0027X-Symlink-Target\u0027: \u0027old_cont/old_tgt\u0027,"},{"line_number":1142,"context_line":"             \u0027X-Symlink-Target-Account\u0027: \u0027a\u0027}, None)"},{"line_number":1143,"context_line":"        self.app.register("},{"line_number":1144,"context_line":"            \u0027PUT\u0027, \u0027/v1/a/ver_cont/007symlink/0000001234.00000\u0027,"},{"line_number":1145,"context_line":"            swob.HTTPCreated, {}, \u0027passed\u0027)"}],"source_content_type":"text/x-python","patch_set":18,"id":"7faddb67_a6a85b78","line":1142,"range":{"start_line":1141,"start_character":12,"end_line":1142,"end_character":45},"updated":"2019-08-22 18:21:07.000000000","message":"?\n\nIn the PUT response??","commit_id":"6081dca15047588197288dae5dceaf2d77113000"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"571fcc99eda5828d26575fba392cacf1fb36fc6d","unresolved":false,"context_lines":[{"line_number":1172,"context_line":"        self.assertEqual(\u0027True\u0027, calls[0].headers[\u0027X-Newest\u0027])"},{"line_number":1173,"context_line":""},{"line_number":1174,"context_line":"        self.assertEqual(\u0027old_cont/old_tgt\u0027,"},{"line_number":1175,"context_line":"                         calls[1].headers[\u0027X-Object-Sysmeta-Symlink-Target\u0027])"},{"line_number":1176,"context_line":""},{"line_number":1177,"context_line":"        self.assertEqual(\u0027new_cont/new_tgt\u0027,"},{"line_number":1178,"context_line":"                         calls[2].headers[\u0027X-Object-Sysmeta-Symlink-Target\u0027])"}],"source_content_type":"text/x-python","patch_set":18,"id":"7faddb67_a6737b4e","line":1175,"updated":"2019-08-22 18:21:07.000000000","message":"Should we assert on target-account, too?","commit_id":"6081dca15047588197288dae5dceaf2d77113000"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"571fcc99eda5828d26575fba392cacf1fb36fc6d","unresolved":false,"context_lines":[{"line_number":1213,"context_line":"                                     \u0027swift.trans_id\u0027: \u0027fake_trans_id\u0027})"},{"line_number":1214,"context_line":"        status, headers, body \u003d self.call_vw(req)"},{"line_number":1215,"context_line":"        self.assertEqual(status, \u0027204 No Content\u0027)"},{"line_number":1216,"context_line":"        self.assertEqual(len(self.authorized), 2)"},{"line_number":1217,"context_line":"        self.assertEqual(3, self.app.call_count)"},{"line_number":1218,"context_line":"        self.assertEqual([\u0027VW\u0027, \u0027VW\u0027, \u0027VW\u0027], self.app.swift_sources)"},{"line_number":1219,"context_line":"        self.assertEqual({\u0027fake_trans_id\u0027}, set(self.app.txn_ids))"}],"source_content_type":"text/x-python","patch_set":18,"id":"7faddb67_23a77dbf","line":1216,"range":{"start_line":1216,"start_character":47,"end_line":1216,"end_character":48},"updated":"2019-08-22 18:21:07.000000000","message":"Hmm... Why\u0027d this go up? I guess.. because of the HEAD?","commit_id":"6081dca15047588197288dae5dceaf2d77113000"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"571fcc99eda5828d26575fba392cacf1fb36fc6d","unresolved":false,"context_lines":[{"line_number":1214,"context_line":"        status, headers, body \u003d self.call_vw(req)"},{"line_number":1215,"context_line":"        self.assertEqual(status, \u0027204 No Content\u0027)"},{"line_number":1216,"context_line":"        self.assertEqual(len(self.authorized), 2)"},{"line_number":1217,"context_line":"        self.assertEqual(3, self.app.call_count)"},{"line_number":1218,"context_line":"        self.assertEqual([\u0027VW\u0027, \u0027VW\u0027, \u0027VW\u0027], self.app.swift_sources)"},{"line_number":1219,"context_line":"        self.assertEqual({\u0027fake_trans_id\u0027}, set(self.app.txn_ids))"},{"line_number":1220,"context_line":""}],"source_content_type":"text/x-python","patch_set":18,"id":"7faddb67_038e0132","line":1217,"updated":"2019-08-22 18:21:07.000000000","message":"I\u0027d prefer that we drop this assertion in favor of just looking at self.app.calls, ideally *before* any other length checks (like with self.app.swift_sources).","commit_id":"6081dca15047588197288dae5dceaf2d77113000"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"571fcc99eda5828d26575fba392cacf1fb36fc6d","unresolved":false,"context_lines":[{"line_number":1231,"context_line":""},{"line_number":1232,"context_line":"        expected_headers \u003d {"},{"line_number":1233,"context_line":"            \u0027x-object-sysmeta-symlink-target\u0027: \u0027ver_cont/003sym/2\u0027,"},{"line_number":1234,"context_line":"            \u0027x-object-sysmeta-symlink-target-etag\u0027: \u0027y\u0027,"},{"line_number":1235,"context_line":"            \u0027x-object-sysmeta-symlink-target-bytes\u0027: \u00270\u0027,"},{"line_number":1236,"context_line":"        }"},{"line_number":1237,"context_line":"        symlink_put_headers \u003d self.app._calls[2].headers"},{"line_number":1238,"context_line":"        for k, v in expected_headers.items():"}],"source_content_type":"text/x-python","patch_set":18,"id":"7faddb67_c3a4694e","line":1235,"range":{"start_line":1234,"start_character":12,"end_line":1235,"end_character":57},"updated":"2019-08-22 18:21:07.000000000","message":"Do we have any tests where the version we\u0027re restoring is a static link?","commit_id":"6081dca15047588197288dae5dceaf2d77113000"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"571fcc99eda5828d26575fba392cacf1fb36fc6d","unresolved":false,"context_lines":[{"line_number":1238,"context_line":"        for k, v in expected_headers.items():"},{"line_number":1239,"context_line":"            self.assertEqual(symlink_put_headers[k], v)"},{"line_number":1240,"context_line":""},{"line_number":1241,"context_line":"        # check that X-If-Delete-At was removed from PUT request"},{"line_number":1242,"context_line":"        req_headers \u003d self.app.headers[-1]"},{"line_number":1243,"context_line":"        self.assertNotIn(\u0027x-if-delete-at\u0027, [h.lower() for h in req_headers])"},{"line_number":1244,"context_line":""}],"source_content_type":"text/x-python","patch_set":18,"id":"7faddb67_e693b3a3","line":1241,"updated":"2019-08-22 18:21:07.000000000","message":"Even if we kept it, it wouldn\u0027t have any impact, yeah?","commit_id":"6081dca15047588197288dae5dceaf2d77113000"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"571fcc99eda5828d26575fba392cacf1fb36fc6d","unresolved":false,"context_lines":[{"line_number":1262,"context_line":""},{"line_number":1263,"context_line":"        cache \u003d FakeCache({\u0027sysmeta\u0027: {\u0027versions-location\u0027: \u0027ver_cont\u0027}})"},{"line_number":1264,"context_line":"        req \u003d Request.blank(\u0027/v1/a/c/sym\u0027, method\u003d\u0027DELETE\u0027, body\u003d\u0027\u0027,"},{"line_number":1265,"context_line":"                            headers\u003d{\u0027X-If-Delete-At\u0027: 1},"},{"line_number":1266,"context_line":"                            environ\u003d{\u0027swift.cache\u0027: cache,"},{"line_number":1267,"context_line":"                                     \u0027swift.trans_id\u0027: \u0027fake_trans_id\u0027})"},{"line_number":1268,"context_line":"        status, headers, body \u003d self.call_vw(req)"}],"source_content_type":"text/x-python","patch_set":18,"id":"7faddb67_4642c711","line":1265,"range":{"start_line":1265,"start_character":37,"end_line":1265,"end_character":56},"updated":"2019-08-22 18:21:07.000000000","message":"OK, so we definitely do the HEAD now, all the time. And we *don\u0027t* see an X-Delete-At header... why wouldn\u0027t we expect this to 412?","commit_id":"6081dca15047588197288dae5dceaf2d77113000"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"571fcc99eda5828d26575fba392cacf1fb36fc6d","unresolved":false,"context_lines":[{"line_number":1328,"context_line":"        self.assertEqual(status, \u0027204 No Content\u0027)"},{"line_number":1329,"context_line":"        self.assertEqual(len(self.authorized), 2)"},{"line_number":1330,"context_line":"        self.assertEqual(4, self.app.call_count)"},{"line_number":1331,"context_line":"        self.assertEqual([\u0027VW\u0027, \u0027VW\u0027, \u0027VW\u0027, \u0027VW\u0027], self.app.swift_sources)"},{"line_number":1332,"context_line":"        self.assertEqual({\u0027fake_trans_id\u0027}, set(self.app.txn_ids))"},{"line_number":1333,"context_line":""},{"line_number":1334,"context_line":"        prefix_listing_prefix \u003d \u0027/v1/a/ver_cont?prefix\u003d003sym/\u0026\u0027"}],"source_content_type":"text/x-python","patch_set":18,"id":"7faddb67_435dd977","line":1331,"updated":"2019-08-22 18:21:07.000000000","message":"I know this is existing behavior, but it seems a little weird to me that *everybody* has a swift source...","commit_id":"6081dca15047588197288dae5dceaf2d77113000"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"571fcc99eda5828d26575fba392cacf1fb36fc6d","unresolved":false,"context_lines":[{"line_number":1352,"context_line":"        for k, v in expected_headers.items():"},{"line_number":1353,"context_line":"            self.assertEqual(symlink_put_headers[k], v)"},{"line_number":1354,"context_line":""},{"line_number":1355,"context_line":"        # check that X-If-Delete-At was removed from PUT request"},{"line_number":1356,"context_line":"        req_headers \u003d self.app.headers[-1]"},{"line_number":1357,"context_line":"        self.assertNotIn(\u0027x-if-delete-at\u0027, [h.lower() for h in req_headers])"},{"line_number":1358,"context_line":""}],"source_content_type":"text/x-python","patch_set":18,"id":"7faddb67_e6d89381","line":1355,"range":{"start_line":1355,"start_character":53,"end_line":1355,"end_character":56},"updated":"2019-08-22 18:21:07.000000000","message":"Surely it\u0027s the DELETE where this makes more of a difference, yeah?","commit_id":"6081dca15047588197288dae5dceaf2d77113000"}],"test/unit/common/middleware/test_versioned_writes.py":[{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"87ab88b82b9057b3882209b28f3f2999cc9150c5","unresolved":false,"context_lines":[{"line_number":428,"context_line":"            \u0027name\u0027: u\u0027\\N{SNOWMAN}-obj\u0027,"},{"line_number":429,"context_line":"            \u0027hash\u0027: \u0027e55cedc11adb39c404b7365f7d6291fa\u0027,"},{"line_number":430,"context_line":"            \u0027last_modified\u0027: \u00272019-07-26T15:09:54.518990\u0027,"},{"line_number":431,"context_line":"            \u0027symlink_path\u0027: \u0027/v1/a/%E2%98%83%2Bversions/007%E2%98%83-obj/\u0027"},{"line_number":432,"context_line":"            \u00271564167931.54836\u0027,"},{"line_number":433,"context_line":"            \u0027content_type\u0027: \u0027application/snowman\u0027,"},{"line_number":434,"context_line":"            \u0027version_symlink\u0027: True,"}],"source_content_type":"text/x-python","patch_set":9,"id":"7faddb67_b2e60416","line":431,"updated":"2019-07-26 21:56:16.000000000","message":"Oooohhh... *there*\u0027s a symlink API wart I hadn\u0027t realized going into this... :-/\n\nI get why we have to quote the path to get it into the override header... kinda unfortunate that we didn\u0027t unquote it as we broke it out into a separate key for the listing. Oh well.","commit_id":"009ebede372747410b242e46c70d2ce431f9ad46"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"fbcc842c304679585740f4ed4164923b3aced748","unresolved":false,"context_lines":[{"line_number":428,"context_line":"            \u0027name\u0027: u\u0027\\N{SNOWMAN}-obj\u0027,"},{"line_number":429,"context_line":"            \u0027hash\u0027: \u0027e55cedc11adb39c404b7365f7d6291fa\u0027,"},{"line_number":430,"context_line":"            \u0027last_modified\u0027: \u00272019-07-26T15:09:54.518990\u0027,"},{"line_number":431,"context_line":"            \u0027symlink_path\u0027: \u0027/v1/a/%E2%98%83%2Bversions/007%E2%98%83-obj/\u0027"},{"line_number":432,"context_line":"            \u00271564167931.54836\u0027,"},{"line_number":433,"context_line":"            \u0027content_type\u0027: \u0027application/snowman\u0027,"},{"line_number":434,"context_line":"            \u0027version_symlink\u0027: True,"}],"source_content_type":"text/x-python","patch_set":9,"id":"7faddb67_a823a5a6","line":431,"in_reply_to":"7faddb67_b2e60416","updated":"2019-08-01 17:42:39.000000000","message":"I think we could do an unquote on the way out if we wanted?  Even if clients were expecting quoted paths the double unquote is normally idempotent?\n\nI don\u0027t really have any basis to form an opinion on preference.  I feel like maybe returning the same quoted paths in headers \u0026 listings is easier for clients to deal with?","commit_id":"009ebede372747410b242e46c70d2ce431f9ad46"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"f699c87cdeaad7bf37d5abaef441e2451f75a0e1","unresolved":false,"context_lines":[{"line_number":433,"context_line":"            \u0027content_type\u0027: \u0027application/snowman\u0027,"},{"line_number":434,"context_line":"            \u0027version_symlink\u0027: True,"},{"line_number":435,"context_line":"        }]"},{"line_number":436,"context_line":"        self.assertEqual(expected, json.loads(body))"},{"line_number":437,"context_line":""},{"line_number":438,"context_line":"    def test_head_container(self):"},{"line_number":439,"context_line":"        self.app.register("}],"source_content_type":"text/x-python","patch_set":9,"id":"7faddb67_adfc683e","line":436,"updated":"2019-07-26 19:51:41.000000000","message":"I\u0027m pretty skeptical that the string/encoding/quoting in this test is 100% correctly representative of a functional integration test - but as good as I could make it it seemed to break when the code failed a functional test, and pass when the code appeared to working with functional spot checking.","commit_id":"009ebede372747410b242e46c70d2ce431f9ad46"},{"author":{"_account_id":9625,"name":"Thiago da Silva","email":"thiagodasilva@gmail.com","username":"thiago"},"change_message_id":"dd73c8a44268244991b7a3212c73bf1b6c28a782","unresolved":false,"context_lines":[{"line_number":1717,"context_line":"        self.assertEqual(self.app.calls, ["},{"line_number":1718,"context_line":"            (\u0027HEAD\u0027, \u0027/v1/a/c/o?symlink\u003dget\u0027),"},{"line_number":1719,"context_line":"            (\u0027GET\u0027, prefix_listing_prefix + \u0027marker\u003d\u0026reverse\u003don\u0027),"},{"line_number":1720,"context_line":"            (\u0027DELETE\u0027, \u0027/v1/a/ver_cont/001o/2\u0027),"},{"line_number":1721,"context_line":"        ])"},{"line_number":1722,"context_line":"        head_req_headers \u003d self.app.headers[0]"},{"line_number":1723,"context_line":"        self.assertIn(\u0027X-Newest\u0027, head_req_headers)"}],"source_content_type":"text/x-python","patch_set":18,"id":"7faddb67_05a6f3ac","line":1720,"updated":"2019-08-26 18:45:09.000000000","message":"looks like we are missing a PUT here so that that a new symlink points to 001o/1","commit_id":"6081dca15047588197288dae5dceaf2d77113000"}],"test/unit/proxy/test_server.py":[{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"571fcc99eda5828d26575fba392cacf1fb36fc6d","unresolved":false,"context_lines":[{"line_number":10973,"context_line":"        headers \u003d readuntil2crlfs(fd)"},{"line_number":10974,"context_line":"        exp \u003d b\u0027HTTP/1.1 201\u0027"},{"line_number":10975,"context_line":"        self.assertEqual(headers[:len(exp)], exp)"},{"line_number":10976,"context_line":"        # Can\u0027t create the versioned file when container doesn\u0027t exist"},{"line_number":10977,"context_line":"        sock \u003d connect_tcp((\u0027localhost\u0027, prolis.getsockname()[1]))"},{"line_number":10978,"context_line":"        fd \u003d sock.makefile(\u0027rwb\u0027)"},{"line_number":10979,"context_line":"        fd.write(b\u0027PUT /v1/a/%swhoops/foo HTTP/1.1\\r\\nHost: \u0027"}],"source_content_type":"text/x-python","patch_set":18,"id":"7faddb67_7091bdf7","line":10976,"range":{"start_line":10976,"start_character":10,"end_line":10976,"end_character":70},"updated":"2019-08-22 18:21:07.000000000","message":"Definitely seems like something we ought to call out in docs if we don\u0027t already. I think I like it better this way, though? Like, make sure everything\u0027s *actually* configured correctly before writing data.\n\nStill, there\u0027s always https://review.opendev.org/#/c/265015/ ...","commit_id":"6081dca15047588197288dae5dceaf2d77113000"}]}
