2001-07-27  Bradford Hovinen  <hovinen@ximian.com>

	* bonobo-config-archiver.c (bonobo_config_archiver_destroy): Don't
	unref the event source or the property bag

	* RELEASE : 1.5.2

2001-07-24  Richard Hestilow  <hestilow@ximian.com>

	* bonobo-config-archiver.c (pb_set_fn): Do sanity checking on
	the rollback ID we get.

2001-07-24  Richard Hestilow  <hestilow@ximian.com>

	* config-log.c (parse_line): Ok, bad fix. Move that to the archiver.

	* bonobo-config-archiver.c (pb_set_fn): Moved here.
	(bonobo_config_archiver_new): Don't aggregate against an EventSource,
	since the PropertyBag already has one and everything will get confused.
	Just use the one the bag has.
	(bonobo_config_archiver_destroy): Don't unref the event source, we
	don't own it any more.	

2001-07-24  Richard Hestilow  <hestilow@ximian.com>

	* config-log.c (parse_line): Fix date parsing to work with DST.

	* bonobo-config-archiver.[ch]: Export a PropertyBag interface that
	has the last_modified date as a read-only property. 

2001-07-24  Bradford Hovinen  <hovinen@ximian.com>

	* bonobo-config-archiver.c (real_sync): Notify listeners with a sync event
	(real_sync): Use correct pointer type when passing to notify_listeners

2001-07-20  Chema Celorio  <chema@celorio.com>

	* RELEASE : 1.5.0

2001-07-17  Bradford Hovinen  <hovinen@ximian.com>

	* bonobo-config-archiver.c (bonobo_config_archiver_new): Add
	mechanism for quitting once the moniker is no longer in use
	(bonobo_config_archiver_new): Make archive a static variable
	(bonobo_config_archiver_new): Explicitly destroy archive when
	program quits
	(timeout_cb): Remove

	* config-log.c (slave_apprise_data): Remove

	* archive.c (archive_unregister_location): 
	(archive_get_location): strdup the string to remove compiler warnings

	* location.c (location_store): Use return value
	(location_store_full_snapshot): Use return value

2001-07-12  Bradford Hovinen  <hovinen@ximian.com>

	* archive.c (archive_destroy): Clear appropriate global archive pointer
	(archive_get_current_location_id): Logic fix.

2001-07-12  Chema Celorio  <chema@celorio.com>

	* Makefile.am (INCLUDES): update to the new location for the xst backends

2001-07-12  Bradford Hovinen  <hovinen@ximian.com>

	* archive.c (archive_get_current_location_id): Only try to store a
	full snapshot if we are in a global archive

	* bonobo-config-archiver.c (bonobo_config_archiver_new): Store
	real_name in archiver_db
	(bonobo_config_archiver_destroy): Use archiver_db->real_name with
	bonobo_url_register

2001-07-10  Bradford Hovinen  <hovinen@ximian.com>

	* default-user.xml: Add sound-properties

	* bonobo-moniker-archiver.c (archiver_resolve): Don't accept
	PropertyBag interface

2001-07-09  Bradford Hovinen  <hovinen@ximian.com>

	* bonobo-config-archiver.c (bonobo_config_archiver_new): Use
	bonobo_object_unref rather than gtk_object_destroy

	* bonobo-moniker-archiver.c (archiver_resolve): Allow PropertyBag
	interface as well
	(parse_name): Set *location to NULL when there is no location

	* archive.c (archive_load): Use .gnome/capplet-archive rather than
	.gnome/control-center
	(archive_set_current_location): Removed unused variables

	* bonobo-config-archiver.c (bonobo_config_archiver_new): Try to
	load the defaults file if no rollback data can be found

2001-07-05  Bradford Hovinen  <hovinen@ximian.com>

	* bonobo-config-archiver.[ch]: Use bonobo-conf rather than
	bonobo-config for include path

	* bonobo-moniker-archiver.c (archiver_resolve): Update call to
	Bonobo_ConfigDatabase_addDatabase

	* bonobo-config-archiver.h: Fix include directories

	* Makefile.am (INCLUDES): Update to use pkg-config standards; add
	BONOBO_CFLAGS
	Include configuration moniker-related material
	(SUBDIRS): Remove
	(bin_PROGRAMS): Added ximian-archiver

2001-07-02  Tambet Ingo  <tambet@ximian.com>

	* default-global.xml: Added display-conf backend.

2001-06-22  Bradford Hovinen  <hovinen@ximian.com>

	* archive.c (archive_get_current_location): Return NULL if the
	location id is NULL
	(archive_get_current_location_id): Return NULL if storing the
	snapshot results in an error

	* location.c (location_store): Add return values for error
	conditions; remove g_warning's and g_critical's
	(location_store_full_snapshot): Folded in store_snapshot_cb; don't
	call location_foreach_backend
	(location_store_full_snapshot): Return error condition; 0 on
	success, -1 if any backend failed

2001-06-21  Bradford Hovinen  <hovinen@ximian.com>

	* location.c (location_do_rollback): Wait for child process to
	terminate
	(run_backend_proc): Take an extra argument -- where to store the
	PID of the child process

	* archive.c (archive_set_current_location): Use
	location_get_changed_backends

	* location.c (location_get_changed_backends): 
	(location_does_backend_change): Implement
	(create_backends_list): 
	(merge_backend_lists): Moved from archive.c

	* config-log.c (dump_log): Don't call close on fd
	(dump_log): Use g_critical on error conditions rather than g_warning

2001-06-20  Bradford Hovinen  <hovinen@ximian.com>

	* config-log.c (slave_data_cb): Dump the log after loading it from
	the slave
	(dump_log): Set first_old to the beginning of the list after the dump
	(do_load): Don't call do_unload
	(socket_data_cb): Check for hang up first
	(do_load): Don't call reset_filenames
	(slave_data_cb): 
	(config_log_write_entry): Call io_buffer_destroy

	* archive.c, Makefile.am: Replace all instances of ximian-config
	with ximian-setup-tools

	* config-log.c (slave_new): Don't apprise slave of new data
	(config_log_write_entry): Dump log after every write

2001-06-19  Bradford Hovinen  <hovinen@ximian.com>

	* archive.c (archive_set_current_location): Free the location path
	as we walk down it.
	(create_backends_list): Implement
	(merge_backend_lists): Implement
	(archive_set_current_location): Call above functions
	(create_backends_list): Get rid of dummy first element
	(archive_set_current_location): Don't use backends->next when
	calling rollback_backends_to

	* location.c (run_backend_proc): Remember to close the writing end
	(location_store): Change g_error to g_critical
	(run_backend_proc): Don't getenv PATH
	(run_backend_proc): Make sure to close other end of pipe in child
	process

2001-06-18  Bradford Hovinen  <hovinen@ximian.com>

	* location.c (location_store): Use GString API

	* config-log.c (slave_data_cb): Don't use == to test IO conditions

2001-06-01  Bradford Hovinen  <hovinen@ximian.com>

	* location.c (run_backend_proc): Don't free path string after
	setting the path

2001-05-26  Chema Celorio  <chema@celorio.com>

	* Makefile.am (ximian_archiverConf.sh): create x_aConf.sh from
	the XIMIAN_ARCHIVER_FOO_CONF varialbes

2001-05-24  Arturo Espinosa Aldama  <arturo@ximian.com>

	* 0.5 RELEASE

2001-05-24  Chema Celorio  <chema@celorio.com>

	* Makefile.am (libximian_archiver_la_SOURCES): add config-
	manger-dialog so that distcheck would pass
	(SUBDIRS): add the . dir because the capplet depends on
	the archiver and we need to build the archiver first
	(libximian_archiver_la_SOURCES): add location-list &
	create-location-dialog
	(ximian_archiverConf.sh): change to XIMIAN_ARVHIER_FOO

2001-05-24  Bradford Hovinen  <hovinen@ximian.com>

	* Makefile.am (SUBDIRS): Added location-manager-capplet

2001-05-22  JP Rosevear  <jpr@ximian.com>

	* config-log.c (bind_socket): use AF_UNIX for the family

	* location.c (run_backend_proc): use putenv() rather than setenv()
	for solaris

	* config-log.c: define the SUN_LEN macro for those systems not
	having it
	(connect_socket): use the more portable domain type, PF_LOCAL
	seems to map to PF_UNIX on linux anyhow

2001-05-12  Chema Celorio  <chema@celorio.com>

	* location.c (location_store_xml): add a carriage return after the
	warning message

2001-05-09  Arturo Espinosa Aldama  <arturo@ximian.com>

	* 0.4 RELEASE

2001-05-05  Bradford Hovinen  <hovinen@ximian.com>

	* Makefile.am (ximian_archiverConf.sh): Add sed expression to
	replace @VERSION@

2001-05-04  Bradford Hovinen  <hovinen@ximian.com>

	* cluster-location.c (cluster_location_do_rollback): Implement

	* location.c (location_do_rollback): Rename from do_rollback; make
	into virtual method
	(location_rollback_backend_to): 
	(location_rollback_backend_by): 
	(location_rollback_id): Update to call virtual method

	* Makefile.am (libximian_archiver_la_SOURCES): 
	(include_HEADERS): Add cluster.[ch], cluster-location.[ch]

2001-05-03  Bradford Hovinen  <hovinen@ximian.com>

	* cluster.[ch]: New class

	* cluster.c (cluster_new): 
	(cluster_load): Implement

	* archive.c (archive_set_arg): Add argument ARG_IS_GLOBAL
	(archive_class_init): Make ARG_PREFIX construct-only
	(archive_construct): Implement
	(do_load): Remove
	(archive_load): Use archive_construct; pass is_global as an
	argument to the object constructor

	* location.c (location_store_xml): Support STORE_DEFAULT
	(store_snapshot_cb): Use STORE_DEFAULT rather than STORE_MASK_PREVIOUS

	* location.h (_StoreType): Add STORE_DEFAULT

	* config-log.c (config_log_get_rollback_id_by_steps): Return the
	current id if the node represents default data

	* main.c (do_add_location): Cast correctly, fixing compiler
	warning

	* config-log.c (config_log_write_entry): Add parameter
	is_default_data; call get_beginning_of_time rather than
	get_current_date iff is_default_data is TRUE
	(get_beginning_of_time): Implement
	(has_nondefaults): Implement. Return TRUE iff the config log
	contains regular (non-default) entries

2001-04-26  Arturo Espinosa  <arturo@ximian.com>

	* location.c: changed g_critical to g_error. If a newer
	version of glib is to be required, change configure.in then.
	* util.h: Set a flag to disable the DEBUG_MSG macro, which
	messes with the frontend<->backend talking.
	
2001-04-24  Bradford Hovinen  <hovinen@ximian.com>

	* location.c (location_store): Use read rather than fread
	(location_add_backend): 
	(location_remove_backend): Save metadata immediately

2001-04-23  Bradford Hovinen  <hovinen@ximian.com>

	* location.c (location_store): Block SIGPIPE
	(location_store): Fix off-by-one bug

	* archive.c (archive_get_current_location_id): Store a full
	snapshot of the system after the default location is created

	* location.c (run_backend_proc): Added parameter do_get to allow
	control of whether pipe is opened to read or write
	(store_snapshot_cb): Implement. Invokes the given backend with
	--get and stores the XML data
	(location_store_full_snapshot): Implement. Stores a complete
	snapshot with all backend data
	(subtract_xml_node): Assume all nodes are the same
	(location_store): Add string termination character
	(location_store): Only store data if any data were actually read

2001-04-22  Bradford Hovinen  <hovinen@ximian.com>

	* config-log.c (config_log_iterate): Use the correct data pointer
	to pass to the callback

	* location.c (location_new): Save the metadata for the newly
	created location right away

	* util.h: Defined DEBUG_MSG macro for debugging messages

	* archive.c (archive_unregister_location): Don't remove the
	location from the tree if the object is marked destroyed

2001-04-21  Bradford Hovinen  <hovinen@ximian.com>

	* archive.c (archive_destroy): Return if the archive was already
	destroyed

	* location.c (location_delete): Unregister the location before
	destroying it

	* config-log.c (config_log_delete): Set deleted flag
	(config_log_destroy): Only dump the log if the log is not marked
	deleted

	* location.c (location_delete): Check return value of rmdir

	* config-log.c (io_buffer_destroy): Call g_io_channel_close to
	close the GIOChannel
	(disconnect_socket): Force the removal of the source id from the
	main loop
	(config_log_destroy): Disconnect the socket after unloading, not
	before

	* location.c (location_delete): Remember to have a NULL at the end
	of arguments to g_strconcat ()

2001-04-20  Bradford Hovinen  <hovinen@ximian.com>

	* config-log.c: Added InputBuffer, removed get_line
	(struct _Slave):
	(struct _ConfigLogPrivate ): Replaced GIOChannel * and FILE * with
	InputBuffer *'s
	(input_buffer_new): Implement. Constructs a new input buffer
	(input_buffer_destroy): Implement. Destroys an input buffer and
	closes the file descriptor
	(input_buffer_cycle): Implement (borrowed from GDict). Reads
	additional data from the input file
	(input_buffer_read_line): Implement (borrowed from GDict). Reads a
	line from the input file and returns a pointer to it
	(input_buffer_write): Implement. Write the indicated string out to
	the channel

2001-04-15  Bradford Hovinen  <hovinen@ximian.com>

	* config-log.c (config_log_set_arg): Create semaphore for
	auto-reloading
	(do_load): Removed locking code
	(load_log_entry): Support prepending log entries to the beginning
	of the log; free entry->date if parsing was unsuccessful
	(config_log_reset_filenames): Unlink socket filename if not owner
	(config_log_reset_filenames): Rebind socket when filename is reset
	(connect_socket): Implement. Creates or connects to the socket
	associated with the config log
	(check_socket_filename): Implement. Checks to see if the filename
	associated with the socket is in use.
	(bind_socket): Implement. Binds the socket to the filename.
	(socket_connect_cb): Implement. Callback issued when a master gets
	a new connection.
	(socket_data_cb): Implement. Callback issued when a slave gets
	data from the master.
	(slave_new): Implement. Creates a new slave structure
	(slave_destroy): Implement. Destroys a slave structure
	(slave_data_cb): Implement. Callback issued when data comes in
	from a slave
	(slave_broadcast_data): Implement. Broadcast the first log entry
	to all the slaves except the given one
	(disconnect_socket): Implement. Disconnects the socket
	(config_log_open): Call connect_socket
	(do_unload): Don't dump the log unless currently the socket owner
	(config_log_write_entry): Broadcast data to slaves or write data
	to socket, depending on whether currently the socket owner

2001-04-14  Bradford Hovinen  <hovinen@ximian.com>

	* config-log.c (do_unload): Add a parameter write_log to tell
	whether to write out the log when unloading
	(config_log_finalize): Implement

	* config-log.[ch]: Put all data fields in ConfigLogPrivate
	structure

2001-04-11  Bradford Hovinen  <hovinen@ximian.com>

	* location.c (run_backend_proc): Make sure to search location of
	XST backends

	* Makefile.am (INCLUDES): Added XST_BACKEND_LOCATION

	* archive.c (archive_set_current_location_id): Don't use different
	prefixes for per-user and global locations; we are assuming here
	that the only person using this globally will be root anyway
	(archive_get_current_location_id): Ditto

	* Makefile.am (INCLUDES): Replace obsolete hcm directory names
	with ximian-config

2001-02-20  Bradford Hovinen  <hovinen@ximian.com>

	* location.c (compare_xml_nodes): Use attr->val rather than
	attr->node

2001-02-19  Bradford Hovinen  <hovinen@ximian.com>

	* location.c (location_foreach_backend): Update to use BackendNote
	(do_rollback): Don't do rollback if the doc is NULL
	(location_store_xml): Return if this location does not contain the
	backend specified
	(location_store_xml): Use fprintf rather than g_warning
	(subtract_xml_node): 
	(merge_xml_nodes): Update child node while iterating

	* config-log.c (config_log_get_rollback_ids_for_date): Remove

	* location.c (location_set_arg): ref inherited object

	* main.c (main): Don't check if the location is default; don't
	create default location if non-existant
	(main): Signal error if the user is adding a location and did not
	specify a name
	(main): Use fprintf to signal the error that a location could not
	be opened
	(main): Signal error and exit when archive cannot be opened,
	rather than using g_error
	(do_add_location): Check for NULL location_id
	(do_add_location): Create default location if it does not exist
	and it is specified as the parent

	* archive.c (archive_get_current_location_id): Create the default
	location if it does not exist

	* backend-list.c (backend_list_contains): Use strcmp and iterate
	through the list

	* location.c (location_contains): Read whether the backend is in
	the master list if this location is toplevel

2001-02-18  Bradford Hovinen  <hovinen@ximian.com>

	* main.c (do_add_backend): Support ContainmentType specification
	(do_store): Support StoreType specification
	(struct store_options): Add set of options to support
	compare_parent, mask_previous, options
	(struct add_remove_backend_options): Add option for partial
	containment when adding backend

	* location.c (subtract_xml_node):
	(merge_xml_nodes):
	(compare_xml_nodes):
	(merge_xml_docs):
	(subtract_xml_doc): Implement. XML node compare/merging operations
	(location_store): Rewrite to call location_store_xml
	(location_store_xml): Include support for diffing with
	configuration data from parent config
	(location_dump_rollback_data): Rewrite to use
	location_load_rollback_data
	(dump_xml_data): Remove
	(do_rollback): Rewrite to use xmlDocDump; pass xmlDocPtr rather
	than id number
	(location_rollback_id): Add node merging support
	(location_rollback_backend_by):
	(location_rollback_backend_to): Rewrite to use
	location_load_rollback_data
	(location_rollback_backends_to): Rewrite to iterate through
	backend list and call location_rollback_backend_to for each
	element
	(location_rollback_all_to): Ditto

2001-02-14  Bradford Hovinen  <hovinen@ximian.com>

	* location.h (_ContainmentType): Introduce. Specifies the type of
	containment (full, partial, none), of a backend in a location

	* location.c: Added struct BackendNote; have backend list include
	type of containment as well as backend id
	(location_contains): Use find_note
	(find_note): Implement. Finds a note for the given backend id in
	the backend list
	(backend_note_new):
	(backend_note_destroy): Implement. Convenience functions for
	creating and destroying backend notes
	(load_metadata_file):
	(write_metadata_file): Read/write type of backend containment
	(full or partial)
	(location_add_backend): Pass parameter telling whether containment
	is partial

2001-01-25  Bradford Hovinen  <hovinen@ximian.com>

	* config-log.c (get_current_date): Use local time rather than
	Greenwich Mean Time

	* location.c (location_store_xml): Implement; copy from
	location_store
	(location_store): Free filename after use

	* archive.c (archive_load): Free prefix only if not global

	* location.c (location_rollback_all_to): Increment array

	* util.c (parse_date): Normalize values

2001-01-24  Bradford Hovinen  <hovinen@ximian.com>

	* config-log.c (do_load): Disabled locking for now

	* archiver-spec: Added fine-grained location management description

2001-01-15  Bradford Hovinen  <hovinen@ximian.com>

	* Makefile.am: Added rule for ximian_archiverConf.sh; add
	installation target for Conf.sh

2001-01-13  Bradford Hovinen  <hovinen@ximian.com>

	* Makefile.am: Replaced occurrences of helix with ximian
	Removed references to ximian_config_manager

2000-12-22  Bradford Hovinen  <hovinen@helixcode.com>

	* archive.c (foreach_cb):
	(archive_foreach_child_location): Use auxillary structure to pass
	data to traversal callback
	(archive_get_location): 
	(archive_register_location): strdup() location ids
	(free_location_cb): free() key

2000-12-20  Bradford Hovinen  <hovinen@helixcode.com>

	* location.c (location_get_parent): Implement

	* archive.c (load_all_locations): Implement
	(foreach_cb): 
	(archive_foreach_child_location): Implement

2000-12-19  Bradford Hovinen  <hovinen@helixcode.com>

	* Makefile.am (bin_PROGRAMS): Changed name of archiver to
	helix-archiver
	(lib_LIBRARIES): Added libhelix_archiver.a
	(helix_archiver_SOURCES): Moved archiver core to
	libhelix_archiver_a_SOURCES
	(helix_archiver_LDADD): Added libhelix_archiver.a
	(INCLUDES): Changed XML_CFLAGS to GNOME_XML_CFLAGS
	(include_HEADERS): Create and include headers for
	libhelix_archiver.a
	(includedir): Set includedire to include/helix-archiver

2000-12-18  Bradford Hovinen  <hovinen@helixcode.com>

	* main.c (do_rollback): Support rolling back by steps

	* location.c (location_rollback_backend_by): Implement
	(location_dump_rollback_data): Support passing steps as well as
	date

	* config-log.c (config_log_get_rollback_id_by_steps): Implement

	* location.c (write_metadata_file): Don't support writing out the
	master list any more
	(save_metadata): Ditto
	(load_metadata_file): Get backends list from BackendList object
	(rather than finding it out oneself) if location is toplevel
	(do_create): Ditto
	(get_backends_cb): Implement
	(location_add_backend): Add return values for error conditions

2000-10-15  Bradford Hovinen  <hovinen@helixcode.com>

	* location.c (location_rollback_backends_to): Free id_array when done

	* config-log.c (config_log_reset_filenames): Implement

	* archive.c (archive_set_current_location_id): Move gnome_config_
 	code from set_current_location

	* location.c (location_set_id): Implement

	* main.c (do_rename_location): Implement

	* archive.c (free_location_cb): Don't free locid
	(archive_get_location):
	(archive_register_location): Don't strdup the location id
	(archive_set_current_location_id): Implement

	* main.c: Add options for renaming locations and specifying that
 	backends should be added to or removed from the master list

	* location.c (run_backend_proc): Close all descriptors other than
	0, 1, 2
	(location_set_id): Implement
	(location_set_arg): Free previous locid if exists

	* archive.c (add_location_cb): Implement
	(archive_set_current_location): Add location change algorithm

	* location.c (location_find_path_from_common_parent): Implement
	(location_foreach_backend): Implement

	* archive.c (archive_set_current_location): Set
	archive->current_location_id

	* main.c (do_add_location): Check parent_str for NULL before
	loading location
	(do_change_location): Implement
	(main): Support changing location

	* archive.c (archive_register_location): Implement

	* location.c (do_create):
	(do_load): Use archive_get_prefix
	(do_create): Load global location metadata if this location does
	not inherit from anything
	(location_get_id): Implement

	* archive.c (archive_get_prefix): Implement

	* location.c (location_get_path): Implement
	(load_metadata_file): Use archive_is_global
	(location_set_arg): Set label when setting locid

	* location.[ch]: Make all data members private

	* main.c (main): Get current location name properly, create
	location iff location id is "default"; bail out with error otherwise
	(do_remove_location): 
	(do_add_location): Implement

	* config-log.c: Include ctype.h to fix implicit declarations

	* location.c (location_rollback_backends_to): Property initialize i
	(location_contains): Fix precondition checks
	(do_create): Remove unused variables

	* archive.c (archive_get_location): Make a copy of locid before
	working with it 
	(do_load): Fix precondition checks

	* location.c (location_open):
	(location_new): Make locid const

	* archive.c (archive_get_location): Make locid const

	* location.c (data_delete_cb): 
	(location_delete): Implement

	* config-log.c (config_log_iterate): Implement
	(config_log_destroy): Make private, pass GtkObject
	(config_log_delete): Implement

2000-10-14  Bradford Hovinen  <hovinen@helixcode.com>

	* location.c (location_close): Add precondition checks

	* archive.c (archive_destroy): Make private; pass GtkObject

	* location.c (location_add_backend): 
	(location_remove_backend): Add precondition checks
	(location_destroy): Make private
	(location_destroy): Pass GtkObject pointer rather than Location
	pointer; this cleans up assignment in _class_init 

	* archive.c (archive_get_current_location_id): Implement
	(archive_get_current_location): Implement

2000-09-03  Bradford Hovinen  <hovinen@helixcode.com>

	* location.c (location_new): Set is_new
	(save_metadata): Don't write file unless necessary
	(save_metadata): 
	(write_metadata_file): Split out file writing into
	write_metadata_file; write default data file as necessary
	(location_add_backend): 
	(location_remove_backend): Implement

	* main.c: Add command line arguments for adding/removing locations 
	and backends; move backend id argument into global options

	* location.c (do_load): 
	(load_metadata_file): Split out file parsing logic into
	load_metadata_file; call load_metadata_file on default file to get 
	contains list if current location doesn't inherit anything
	(load_metadata_file): g_strdup backend string
	(load_metadata_file): Warn if top-level location has contains clauses
	(location_store): Check if the location contains the given backend
	and try the location it inherits if it doesn't

	* archive.c (archive_load): Set is_global in archive object

	* Makefile.am (Locationmeta{dir|_DATA}): Added commands to install
	data files
	(INCLUDES): Added define for LOCATION_DIR

2000-09-03  Bradford Hovinen  <hovinen@helixcode.com>

	* location.c (save_metadata): Write attributes when saving

