Index: pathauto.module
===================================================================
RCS file: /cvs/drupal/contributions/modules/pathauto/pathauto.module,v
retrieving revision 1.169
diff -u -p -r1.169 pathauto.module
--- pathauto.module	13 Jan 2011 03:27:24 -0000	1.169
+++ pathauto.module	12 Feb 2011 00:33:16 -0000
@@ -297,6 +297,23 @@ function pathauto_node_insert($node) {
  * Implements hook_node_update().
  */
 function pathauto_node_update($node) {
+  // Initialize $node->path['pathauto'] similarly to pathauto_form_alter(), but
+  // for when code calls node_load() ... node_save() without invoking a node
+  // form submission.
+  // @todo This is a temporary workaround until pathauto_persist is merged into
+  //   pathauto: http://drupal.org/node/936222.
+  if (!isset($node->path['pathauto']) && !empty($node->nid) && !empty($node->original->nid)) {
+    $original = $node->original;
+    $language = isset($original->language) ? $original->language : LANGUAGE_NONE;
+    $pattern = pathauto_pattern_load_by_entity('node', $original->type, $language);
+    if ($pattern) {
+      module_load_include('inc', 'pathauto');
+      $uri = entity_uri('node', $original);
+      $path = drupal_get_path_alias($uri['path'], $language);
+      $pathauto_alias = pathauto_create_alias('node', 'return', $uri['path'], array('node' => $original), $original->type, $original->language);
+      $node->path['pathauto'] = $path != $uri['path'] && $path == $pathauto_alias;
+    }
+  }
   pathauto_node_update_alias($node, 'update');
 }
 
Index: pathauto.test
===================================================================
RCS file: /cvs/drupal/contributions/modules/pathauto/pathauto.test,v
retrieving revision 1.38
diff -u -p -r1.38 pathauto.test
--- pathauto.test	13 Jan 2011 03:27:24 -0000	1.38
+++ pathauto.test	12 Feb 2011 00:33:19 -0000
@@ -391,6 +391,62 @@ class PathautoFunctionalTestCase extends
   }
 
   /**
+   * Test alias integrity when client code loads, modifies, and saves a node.
+   */
+  function testNodeAPI() {
+    variable_set('pathauto_node_pattern', 'content/[node:title]');
+    $nodes = array(
+      'auto' => array(
+      ),
+      'custom' => array(
+        'path' => array(
+          'alias' => 'custom',
+          'pathauto' => FALSE,
+        ),
+      ),
+      'none' => array(
+        'path' => array(
+          'alias' => NULL,
+          'pathauto' => FALSE,
+        ),
+      ),
+    );
+    foreach ($nodes as $key => $info) {
+      $this->deleteAllAliases();
+      $info['title'] = 'First title';
+      $node = $this->drupalCreateNode($info);
+      switch ($key) {
+        case 'auto':
+          $this->assertEntityAlias('node', $node, 'content/first-title');
+          break;
+        case 'custom':
+          $this->assertEntityAlias('node', $node, 'custom');
+          break;
+        case 'none':
+          $this->assertNoEntityAliasExists('node', $node);
+          break;
+      }
+      $node = node_load($node->nid, NULL, TRUE);
+      $node->title = 'Second title';
+      node_save($node);
+      switch ($key) {
+        case 'auto':
+          $this->assertEntityAlias('node', $node, 'content/second-title');
+          $this->assertNoAliasExists(array('alias' => 'content/first-title'));
+          break;
+        case 'custom':
+          $this->assertEntityAlias('node', $node, 'custom');
+          $this->assertNoAliasExists(array('alias' => 'content/first-title'));
+          $this->assertNoAliasExists(array('alias' => 'content/second-title'));
+          break;
+        case 'none':
+          $this->assertNoEntityAliasExists('node', $node);
+          break;
+      }
+    }
+  }
+
+  /**
    * Test node operations.
    */
   function testNodeOperations() {
